@gitlab/ui 67.5.1 → 68.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Do not edit directly
3
- * Generated on Fri, 03 Nov 2023 15:03:12 GMT
3
+ * Generated on Tue, 07 Nov 2023 12:38:00 GMT
4
4
  */
5
5
 
6
6
  :root {
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Do not edit directly
3
- * Generated on Fri, 03 Nov 2023 15:03:12 GMT
3
+ * Generated on Tue, 07 Nov 2023 12:38:00 GMT
4
4
  */
5
5
 
6
6
  :root.gl-dark {
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Do not edit directly
3
- * Generated on Fri, 03 Nov 2023 15:03:12 GMT
3
+ * Generated on Tue, 07 Nov 2023 12:38:00 GMT
4
4
  */
5
5
 
6
6
  export const BLACK = "#fff";
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Do not edit directly
3
- * Generated on Fri, 03 Nov 2023 15:03:12 GMT
3
+ * Generated on Tue, 07 Nov 2023 12:38:00 GMT
4
4
  */
5
5
 
6
6
  export const BLACK = "#000";
@@ -1,6 +1,6 @@
1
1
 
2
2
  // Do not edit directly
3
- // Generated on Fri, 03 Nov 2023 15:03:12 GMT
3
+ // Generated on Tue, 07 Nov 2023 12:38:00 GMT
4
4
 
5
5
  $red-950: #fff4f3;
6
6
  $red-900: #fcf1ef;
@@ -1,6 +1,6 @@
1
1
 
2
2
  // Do not edit directly
3
- // Generated on Fri, 03 Nov 2023 15:03:12 GMT
3
+ // Generated on Tue, 07 Nov 2023 12:38:00 GMT
4
4
 
5
5
  $gl-line-height-52: 3.25rem;
6
6
  $gl-line-height-44: 2.75rem;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gitlab/ui",
3
- "version": "67.5.1",
3
+ "version": "68.0.0",
4
4
  "description": "GitLab UI Components",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",
@@ -124,9 +124,10 @@
124
124
  "bootstrap": "4.6.2",
125
125
  "cypress": "13.4.0",
126
126
  "cypress-axe": "^1.4.0",
127
+ "cypress-real-events": "^1.11.0",
127
128
  "dompurify": "^3.0.0",
128
129
  "emoji-regex": "^10.0.0",
129
- "eslint": "8.52.0",
130
+ "eslint": "8.53.0",
130
131
  "eslint-import-resolver-jest": "3.0.2",
131
132
  "eslint-plugin-cypress": "2.15.1",
132
133
  "eslint-plugin-storybook": "0.6.15",
@@ -17,7 +17,7 @@ $legend-body-h: $gl-spacing-scale-13 - $gl-spacing-scale-4;
17
17
  .gl-legend-tabular,
18
18
  .gl-chart-h-auto .gl-legend-inline {
19
19
  &::after {
20
- background-image: linear-gradient(to bottom, $transparent-rgba, $white);
20
+ background-image: linear-gradient(to bottom, $transparent-rgba, var(--white, #{$white}));
21
21
  @include gl-bottom-0;
22
22
  @include gl-content-empty;
23
23
  @include gl-display-block;
@@ -31,7 +31,6 @@ $legend-body-h: $gl-spacing-scale-13 - $gl-spacing-scale-4;
31
31
  @include gl-display-flex;
32
32
  @include gl-flex-wrap;
33
33
  @include gl-flex-shrink-0;
34
- @include gl-text-gray-900;
35
34
 
36
35
  .gl-legend-inline-series {
37
36
  @include gl-display-flex;
@@ -75,14 +74,14 @@ $legend-body-h: $gl-spacing-scale-13 - $gl-spacing-scale-4;
75
74
  .gl-legend-tabular-body {
76
75
  height: $legend-body-h;
77
76
  @include gl-overflow-y-auto;
78
-
79
- > *:nth-child(odd) {
80
- @include gl-bg-gray-10;
81
- }
82
77
  }
83
78
 
84
79
  .gl-legend-tabular-row {
85
80
  @include gl-display-flex;
81
+
82
+ &:nth-child(odd) {
83
+ background-color: var(--gray-50, #{$gray-50});
84
+ }
86
85
  }
87
86
 
88
87
  .gl-legend-tabular-title-cell,
@@ -160,12 +160,25 @@ describe('GlDuoChat', () => {
160
160
  });
161
161
 
162
162
  it('sets correct props on the Experiment badge', () => {
163
- const experimentHelpPageUrl = 'https://foo.bar';
163
+ const badgeHelpPageUrl = 'https://foo.bar';
164
164
  const containerId = 'chat-component';
165
- createComponent({ propsData: { experimentHelpPageUrl } });
166
- expect(findBadge().props('experimentHelpPageUrl')).toBe(experimentHelpPageUrl);
165
+ createComponent({ propsData: { badgeHelpPageUrl } });
166
+ expect(findBadge().props('helpPageUrl')).toBe(badgeHelpPageUrl);
167
167
  expect(findBadge().attributes('container-id')).toBe(containerId);
168
168
  });
169
+
170
+ it.each`
171
+ badgeType | expectedProp
172
+ ${'experiment'} | ${'experiment'}
173
+ ${'beta'} | ${'beta'}
174
+ ${undefined} | ${'experiment'}
175
+ `(
176
+ 'sets correct props on the Experiment badge when badgeType is "$badgeType"',
177
+ ({ badgeType, expectedProp }) => {
178
+ createComponent({ propsData: { badgeType } });
179
+ expect(findBadge().props('type')).toBe(expectedProp);
180
+ }
181
+ );
169
182
  });
170
183
 
171
184
  describe('chat', () => {
@@ -24,7 +24,8 @@ const generateProps = ({
24
24
  isLoading = defaultValue('isLoading'),
25
25
  isChatAvailable = defaultValue('isChatAvailable'),
26
26
  predefinedPrompts = defaultValue('predefinedPrompts'),
27
- experimentHelpPageUrl = defaultValue('experimentHelpPageUrl'),
27
+ badgeHelpPageUrl = defaultValue('badgeHelpPageUrl'),
28
+ badgeType = defaultValue('badgeType'),
28
29
  toolName = defaultValue('toolName'),
29
30
  } = {}) => ({
30
31
  title,
@@ -33,7 +34,8 @@ const generateProps = ({
33
34
  isLoading,
34
35
  isChatAvailable,
35
36
  predefinedPrompts,
36
- experimentHelpPageUrl,
37
+ badgeHelpPageUrl,
38
+ badgeType,
37
39
  toolName,
38
40
  });
39
41
 
@@ -52,7 +54,8 @@ export const Default = (args, { argTypes }) => ({
52
54
  :is-loading="isLoading"
53
55
  :is-chat-available="isChatAvailable"
54
56
  :predefined-prompts="predefinedPrompts"
55
- :experiment-help-page-url="experimentHelpPageUrl"
57
+ :badge-help-page-url="badgeHelpPageUrl"
58
+ :badge-type="badgeType"
56
59
  :tool-name="toolName"
57
60
  />`,
58
61
  });
@@ -145,7 +148,8 @@ export const Interactive = (args, { argTypes }) => ({
145
148
  :is-loading="promptInFlight"
146
149
  :is-chat-available="isChatAvailable"
147
150
  :predefined-prompts="predefinedPrompts"
148
- :experiment-help-page-url="experimentHelpPageUrl"
151
+ :badge-help-page-url="badgeHelpPageUrl"
152
+ :badge-type="badgeType"
149
153
  :tool-name="toolName"
150
154
  @send-chat-prompt="onSendChatPrompt"
151
155
  @chat-hidden="onChatHidden"
@@ -170,7 +174,8 @@ export const Slots = (args, { argTypes }) => ({
170
174
  :is-loading="isLoading"
171
175
  :is-chat-available="isChatAvailable"
172
176
  :predefined-prompts="predefinedPrompts"
173
- :experiment-help-page-url="experimentHelpPageUrl"
177
+ :badge-help-page-url="badgeHelpPageUrl"
178
+ :badge-type="badgeType"
174
179
  :tool-name="toolName">
175
180
 
176
181
  <template #hero>
@@ -9,6 +9,7 @@ import GlFormTextarea from '../../../base/form/form_textarea/form_textarea.vue';
9
9
  import GlForm from '../../../base/form/form.vue';
10
10
  import GlFormText from '../../../base/form/form_text/form_text.vue';
11
11
  import GlExperimentBadge from '../../experiment_badge/experiment_badge.vue';
12
+ import { badgeTypes, badgeTypeValidator } from '../../experiment_badge/constants';
12
13
  import { SafeHtmlDirective as SafeHtml } from '../../../../directives/safe_html/safe_html';
13
14
  import GlDuoChatLoader from './components/duo_chat_loader/duo_chat_loader.vue';
14
15
  import GlDuoChatPredefinedPrompts from './components/duo_chat_predefined_prompts/duo_chat_predefined_prompts.vue';
@@ -106,13 +107,22 @@ export default {
106
107
  default: () => i18n.CHAT_DEFAULT_PREDEFINED_PROMPTS,
107
108
  },
108
109
  /**
109
- * URL to the experiment help page. This is passed down to the `GlExperimentBadge` component. Refer that component for more information.
110
+ * URL to the experiment/beta help page. This is passed down to the `GlExperimentBadge` component. Refer that component for more information.
110
111
  */
111
- experimentHelpPageUrl: {
112
+ badgeHelpPageUrl: {
112
113
  type: String,
113
114
  required: false,
114
115
  default: '',
115
116
  },
117
+ /**
118
+ * The type of the badge. This is passed down to the `GlExperimentBadge` component. Refer that component for more information.
119
+ */
120
+ badgeType: {
121
+ type: String,
122
+ required: false,
123
+ default: badgeTypes[0],
124
+ validator: badgeTypeValidator,
125
+ },
116
126
  /**
117
127
  * The current tool's name to display in the loading message while waiting for a response from AI. Refer the `GlDuoChatLoader` component for more information.
118
128
  */
@@ -236,7 +246,8 @@ export default {
236
246
  >
237
247
  <h3 class="gl-my-0 gl-font-size-h2">{{ title }}</h3>
238
248
  <gl-experiment-badge
239
- :experiment-help-page-url="experimentHelpPageUrl"
249
+ :help-page-url="badgeHelpPageUrl"
250
+ :type="badgeType"
240
251
  container-id="chat-component"
241
252
  />
242
253
  <gl-button
@@ -0,0 +1,2 @@
1
+ export const badgeTypes = ['experiment', 'beta'];
2
+ export const badgeTypeValidator = (value) => badgeTypes.includes(value);
@@ -34,19 +34,6 @@ describe('GlExperimentBadge', () => {
34
34
  expect(findPopover().exists()).toBe(true);
35
35
  });
36
36
 
37
- it('sets correct props on the badge', () => {
38
- const badgeType = 'neutral';
39
- const badgeSize = 'md';
40
- expect(findBadge().props('variant')).toBe(badgeType);
41
- expect(findBadge().props('size')).toBe(badgeSize);
42
- expect(findBadge().find('span').text()).toBe(i18n.EXPERIMENT_BADGE);
43
- });
44
-
45
- it('sets correct props on the popover', () => {
46
- expect(findPopover().props('triggers')).toBe('click');
47
- expect(findPopover().props('title')).toBe(i18n.EXPERIMENT_POPOVER_TITLE);
48
- });
49
-
50
37
  it('correctly sets the placement of the popover', () => {
51
38
  const popoverPlacement = 'right';
52
39
  createComponent({ popoverPlacement });
@@ -54,13 +41,37 @@ describe('GlExperimentBadge', () => {
54
41
  });
55
42
 
56
43
  it('sets the link to the help page if passed', () => {
57
- const experimentHelpPageUrl = 'https://gitlab.com';
58
- createComponent({ experimentHelpPageUrl });
59
- expect(findHelpLink().attributes('href')).toBe(experimentHelpPageUrl);
44
+ const helpPageUrl = 'https://gitlab.com';
45
+ createComponent({ helpPageUrl });
46
+ expect(findHelpLink().attributes('href')).toBe(helpPageUrl);
60
47
  });
61
48
 
62
49
  it('generates the unique ID to connect the button and the popover', () => {
63
50
  expect(findBadge().attributes('id')).toBe('fakeUniqueId');
64
51
  expect(findPopover().attributes('target')).toBe('fakeUniqueId');
65
52
  });
53
+
54
+ describe.each`
55
+ type | expectedType
56
+ ${'beta'} | ${'beta'}
57
+ ${'experiment'} | ${'experiment'}
58
+ ${undefined} | ${'experiment'}
59
+ `('when type is %s', ({ type, expectedType } = {}) => {
60
+ beforeEach(() => {
61
+ createComponent({ type });
62
+ });
63
+
64
+ it('sets correct props on the badge', () => {
65
+ const badgeVariant = 'neutral';
66
+ const badgeSize = 'md';
67
+ expect(findBadge().props('variant')).toBe(badgeVariant);
68
+ expect(findBadge().props('size')).toBe(badgeSize);
69
+ expect(findBadge().find('span').text()).toBe(i18n[expectedType].BADGE);
70
+ });
71
+
72
+ it('sets correct props on the popover', () => {
73
+ expect(findPopover().props('triggers')).toBe('click');
74
+ expect(findPopover().props('title')).toBe(i18n[expectedType].POPOVER_TITLE);
75
+ });
76
+ });
66
77
  });
@@ -4,11 +4,13 @@ import readme from './experiment_badge.md';
4
4
  const defaultValue = (prop) => GlExperimentBadge.props[prop].default;
5
5
 
6
6
  const generateProps = ({
7
- experimentHelpPageUrl = defaultValue('experimentHelpPageUrl'),
7
+ helpPageUrl = defaultValue('helpPageUrl'),
8
8
  popoverPlacement = defaultValue('popoverPlacement'),
9
+ type = defaultValue('type'),
9
10
  } = {}) => ({
10
- experimentHelpPageUrl,
11
+ helpPageUrl,
11
12
  popoverPlacement,
13
+ type,
12
14
  });
13
15
 
14
16
  const Template = (args, { argTypes }) => ({
@@ -17,8 +19,9 @@ const Template = (args, { argTypes }) => ({
17
19
  template: `
18
20
  <div class='gl-h-13'>
19
21
  <gl-experiment-badge
20
- :experiment-help-page-url='experimentHelpPageUrl'
21
- :popover-placement='popoverPlacement' />
22
+ :help-page-url='helpPageUrl'
23
+ :popover-placement='popoverPlacement'
24
+ :type='type' />
22
25
  </div>
23
26
  `,
24
27
  });
@@ -4,22 +4,36 @@ import GlBadge from '../../base/badge/badge.vue';
4
4
  import GlLink from '../../base/link/link.vue';
5
5
  import GlPopover from '../../base/popover/popover.vue';
6
6
  import GlSprintf from '../../utilities/sprintf/sprintf.vue';
7
+ import { badgeTypes, badgeTypeValidator } from './constants';
7
8
 
8
9
  export const i18n = {
9
- EXPERIMENT_BADGE: 'Experiment',
10
- EXPERIMENT_POPOVER_TITLE: "What's an Experiment?",
11
- EXPERIMENT_POPOVER_CONTENT:
12
- "An %{linkStart}Experiment%{linkEnd} is a feature that's in the process of being developed. It's not production-ready. We encourage users to try Experimental features and provide feedback. An Experiment: %{bullets}",
13
- EXPERIMENT_POPOVER_BULLETS: [
14
- 'May be unstable',
15
- 'Has no support and might not be documented',
16
- 'Can be removed at any time',
17
- ],
10
+ experiment: {
11
+ BADGE: 'Experiment',
12
+ POPOVER_TITLE: "What's an Experiment?",
13
+ POPOVER_CONTENT:
14
+ "An %{linkStart}Experiment%{linkEnd} is a feature that's in the process of being developed. It's not production-ready. We encourage users to try Experimental features and provide feedback. An Experiment: %{bullets}",
15
+ POPOVER_BULLETS: [
16
+ 'May be unstable',
17
+ 'Has no support and might not be documented',
18
+ 'Can be removed at any time',
19
+ ],
20
+ },
21
+ beta: {
22
+ BADGE: 'Beta',
23
+ POPOVER_TITLE: "What's a Beta?",
24
+ POPOVER_CONTENT:
25
+ "A %{linkStart}Beta%{linkEnd} feature is not production-ready, but is unlikely to change drastically before it's released. We encourage users to try Beta features and provide feedback.\nA Beta feature: %{bullets}",
26
+ POPOVER_BULLETS: [
27
+ 'May be unstable',
28
+ 'Should not cause data loss',
29
+ 'Is supported by a commercially reasonable effort',
30
+ 'Is complete or near completion',
31
+ ],
32
+ },
18
33
  };
19
34
 
20
35
  export default {
21
36
  name: 'GlExperimentBadge',
22
- i18n,
23
37
  components: {
24
38
  GlBadge,
25
39
  GlPopover,
@@ -30,7 +44,7 @@ export default {
30
44
  /**
31
45
  * The URL of a page to provide more explanations on the experiment.
32
46
  */
33
- experimentHelpPageUrl: {
47
+ helpPageUrl: {
34
48
  type: String,
35
49
  required: false,
36
50
  default: '',
@@ -43,6 +57,20 @@ export default {
43
57
  required: false,
44
58
  default: 'bottom',
45
59
  },
60
+ /**
61
+ * The type of the badge.
62
+ */
63
+ type: {
64
+ type: String,
65
+ required: false,
66
+ default: badgeTypes[0],
67
+ validator: badgeTypeValidator,
68
+ },
69
+ },
70
+ computed: {
71
+ activeType() {
72
+ return i18n[this.type];
73
+ },
46
74
  },
47
75
  created() {
48
76
  this.triggerId = uniqueId('experiment-badge-');
@@ -52,30 +80,25 @@ export default {
52
80
 
53
81
  <template>
54
82
  <gl-badge :id="triggerId" class="gl-mx-4 gl-hover-cursor-pointer" variant="neutral" size="md">
55
- <span>{{ $options.i18n.EXPERIMENT_BADGE }}</span>
83
+ <span>{{ activeType.BADGE }}</span>
56
84
  <gl-popover
57
85
  triggers="click"
58
86
  show-close-button
59
87
  :placement="popoverPlacement"
60
88
  :target="triggerId"
61
89
  :css-classes="['gl-z-index-9999!']"
62
- :title="$options.i18n.EXPERIMENT_POPOVER_TITLE"
90
+ :title="activeType.POPOVER_TITLE"
63
91
  >
64
- <gl-sprintf :message="$options.i18n.EXPERIMENT_POPOVER_CONTENT">
92
+ <gl-sprintf :message="activeType.POPOVER_CONTENT">
65
93
  <template #link="{ content }">
66
- <gl-link
67
- v-if="experimentHelpPageUrl"
68
- :href="experimentHelpPageUrl"
69
- target="_blank"
70
- class="gl-font-sm!"
71
- >
94
+ <gl-link v-if="helpPageUrl" :href="helpPageUrl" target="_blank" class="gl-font-sm!">
72
95
  {{ content }}
73
96
  </gl-link>
74
97
  <span v-else>{{ content }}</span>
75
98
  </template>
76
99
  <template #bullets>
77
100
  <ul class="gl-mb-0 gl-pl-5">
78
- <li v-for="(item, i) in $options.i18n.EXPERIMENT_POPOVER_BULLETS" :key="`li-${i}`">
101
+ <li v-for="(item, i) in activeType.POPOVER_BULLETS" :key="`li-${i}`">
79
102
  {{ item }}
80
103
  </li>
81
104
  </ul>
@@ -15,6 +15,9 @@
15
15
  // Note that we are assigning variables with different values due to the way GitLab inverts variables in dark mode.
16
16
  // e.g. text color is usually $gray-900, but in dark mode $gray-900 variable gets inverted to $gray-50
17
17
  --gl-text-color: #{$gray-50};
18
+ --white: #{$gray-900}; // define mapping between the colours in dark mode. I have used the values from GitLab for consistency: https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/assets/stylesheets/themes/_dark.scss
19
+ --gray-10: #{$gray-950};
20
+ --gray-600: #{$gray-300};
18
21
 
19
22
  color-scheme: dark;
20
23