@gitlab/ui 67.5.2 → 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.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,18 @@
1
+ # [68.0.0](https://gitlab.com/gitlab-org/gitlab-ui/compare/v67.5.2...v68.0.0) (2023-11-07)
2
+
3
+
4
+ ### Features
5
+
6
+ * **GlExperimentBadge:** support 'beta' type ([927f830](https://gitlab.com/gitlab-org/gitlab-ui/commit/927f8302be7bcf471650228b25ee526332b2ff16))
7
+
8
+
9
+ ### BREAKING CHANGES
10
+
11
+ * **GlExperimentBadge:** To extend the capabilities of the
12
+ badge, now it suports not only experiments, but
13
+ also allows to move features to beta state
14
+ using the same component
15
+
1
16
  ## [67.5.2](https://gitlab.com/gitlab-org/gitlab-ui/compare/v67.5.1...v67.5.2) (2023-11-06)
2
17
 
3
18
 
@@ -8,6 +8,7 @@ import GlFormTextarea from '../../../base/form/form_textarea/form_textarea';
8
8
  import GlForm from '../../../base/form/form';
9
9
  import GlFormText from '../../../base/form/form_text/form_text';
10
10
  import GlExperimentBadge from '../../experiment_badge/experiment_badge';
11
+ import { badgeTypes, badgeTypeValidator } from '../../experiment_badge/constants';
11
12
  import { SafeHtmlDirective } from '../../../../directives/safe_html/safe_html';
12
13
  import GlDuoChatLoader from './components/duo_chat_loader/duo_chat_loader';
13
14
  import GlDuoChatPredefinedPrompts from './components/duo_chat_predefined_prompts/duo_chat_predefined_prompts';
@@ -97,13 +98,22 @@ var script = {
97
98
  default: () => i18n.CHAT_DEFAULT_PREDEFINED_PROMPTS
98
99
  },
99
100
  /**
100
- * URL to the experiment help page. This is passed down to the `GlExperimentBadge` component. Refer that component for more information.
101
+ * URL to the experiment/beta help page. This is passed down to the `GlExperimentBadge` component. Refer that component for more information.
101
102
  */
102
- experimentHelpPageUrl: {
103
+ badgeHelpPageUrl: {
103
104
  type: String,
104
105
  required: false,
105
106
  default: ''
106
107
  },
108
+ /**
109
+ * The type of the badge. This is passed down to the `GlExperimentBadge` component. Refer that component for more information.
110
+ */
111
+ badgeType: {
112
+ type: String,
113
+ required: false,
114
+ default: badgeTypes[0],
115
+ validator: badgeTypeValidator
116
+ },
107
117
  /**
108
118
  * 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.
109
119
  */
@@ -215,7 +225,7 @@ var script = {
215
225
  const __vue_script__ = script;
216
226
 
217
227
  /* template */
218
- var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return (!_vm.isHidden)?_c('aside',{ref:"drawer",staticClass:"markdown-code-block gl-drawer gl-drawer-default gl-max-h-full gl-bottom-0 gl-shadow-none gl-border-l gl-border-t duo-chat",attrs:{"id":"chat-component","role":"complementary","data-testid":"chat-component"},on:{"scroll":_vm.handleScrollingTrottled}},[_c('header',{staticClass:"gl-drawer-header gl-drawer-header-sticky gl-z-index-200 gl-p-0! gl-border-b-0"},[_c('div',{staticClass:"drawer-title gl-display-flex gl-justify-content-start gl-align-items-center gl-p-5"},[_c('h3',{staticClass:"gl-my-0 gl-font-size-h2"},[_vm._v(_vm._s(_vm.title))]),_vm._v(" "),_c('gl-experiment-badge',{attrs:{"experiment-help-page-url":_vm.experimentHelpPageUrl,"container-id":"chat-component"}}),_vm._v(" "),_c('gl-button',{staticClass:"gl-p-0! gl-ml-auto",attrs:{"category":"tertiary","variant":"default","icon":"close","size":"small","data-testid":"chat-close-button","aria-label":_vm.$options.i18n.CHAT_CLOSE_LABEL},on:{"click":_vm.hideChat}})],1),_vm._v(" "),_c('gl-alert',{staticClass:"gl-text-center gl-border-t gl-p-4 gl-text-gray-700 gl-bg-gray-50 legal-warning gl-max-w-full",attrs:{"dismissible":false,"variant":"tip","show-icon":false,"role":"alert","data-testid":"chat-legal-warning"}},[_vm._v(_vm._s(_vm.$options.i18n.CHAT_LEGAL_GENERATED_BY_AI))]),_vm._v(" "),_vm._t("subheader")],2),_vm._v(" "),_c('div',{staticClass:"gl-drawer-body gl-display-flex gl-flex-direction-column"},[_vm._t("hero"),_vm._v(" "),(_vm.error)?_c('gl-alert',{key:"error",staticClass:"gl-mb-0 gl-pl-9!",attrs:{"dismissible":false,"variant":"danger","role":"alert","data-testid":"chat-error"}},[_c('span',{directives:[{name:"safe-html",rawName:"v-safe-html",value:(_vm.error),expression:"error"}]})]):_vm._e(),_vm._v(" "),_c('section',{staticClass:"gl-display-flex gl-flex-direction-column gl-justify-content-end gl-flex-grow-1 gl-border-b-0 gl-bg-gray-10"},[_c('transition-group',{staticClass:"gl-display-flex gl-flex-direction-column gl-justify-content-end",class:[
228
+ var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return (!_vm.isHidden)?_c('aside',{ref:"drawer",staticClass:"markdown-code-block gl-drawer gl-drawer-default gl-max-h-full gl-bottom-0 gl-shadow-none gl-border-l gl-border-t duo-chat",attrs:{"id":"chat-component","role":"complementary","data-testid":"chat-component"},on:{"scroll":_vm.handleScrollingTrottled}},[_c('header',{staticClass:"gl-drawer-header gl-drawer-header-sticky gl-z-index-200 gl-p-0! gl-border-b-0"},[_c('div',{staticClass:"drawer-title gl-display-flex gl-justify-content-start gl-align-items-center gl-p-5"},[_c('h3',{staticClass:"gl-my-0 gl-font-size-h2"},[_vm._v(_vm._s(_vm.title))]),_vm._v(" "),_c('gl-experiment-badge',{attrs:{"help-page-url":_vm.badgeHelpPageUrl,"type":_vm.badgeType,"container-id":"chat-component"}}),_vm._v(" "),_c('gl-button',{staticClass:"gl-p-0! gl-ml-auto",attrs:{"category":"tertiary","variant":"default","icon":"close","size":"small","data-testid":"chat-close-button","aria-label":_vm.$options.i18n.CHAT_CLOSE_LABEL},on:{"click":_vm.hideChat}})],1),_vm._v(" "),_c('gl-alert',{staticClass:"gl-text-center gl-border-t gl-p-4 gl-text-gray-700 gl-bg-gray-50 legal-warning gl-max-w-full",attrs:{"dismissible":false,"variant":"tip","show-icon":false,"role":"alert","data-testid":"chat-legal-warning"}},[_vm._v(_vm._s(_vm.$options.i18n.CHAT_LEGAL_GENERATED_BY_AI))]),_vm._v(" "),_vm._t("subheader")],2),_vm._v(" "),_c('div',{staticClass:"gl-drawer-body gl-display-flex gl-flex-direction-column"},[_vm._t("hero"),_vm._v(" "),(_vm.error)?_c('gl-alert',{key:"error",staticClass:"gl-mb-0 gl-pl-9!",attrs:{"dismissible":false,"variant":"danger","role":"alert","data-testid":"chat-error"}},[_c('span',{directives:[{name:"safe-html",rawName:"v-safe-html",value:(_vm.error),expression:"error"}]})]):_vm._e(),_vm._v(" "),_c('section',{staticClass:"gl-display-flex gl-flex-direction-column gl-justify-content-end gl-flex-grow-1 gl-border-b-0 gl-bg-gray-10"},[_c('transition-group',{staticClass:"gl-display-flex gl-flex-direction-column gl-justify-content-end",class:[
219
229
  {
220
230
  'gl-h-full': !_vm.hasMessages,
221
231
  'gl-h-auto': _vm.hasMessages,
@@ -0,0 +1,4 @@
1
+ const badgeTypes = ['experiment', 'beta'];
2
+ const badgeTypeValidator = value => badgeTypes.includes(value);
3
+
4
+ export { badgeTypeValidator, badgeTypes };
@@ -3,17 +3,25 @@ import GlBadge from '../../base/badge/badge';
3
3
  import GlLink from '../../base/link/link';
4
4
  import GlPopover from '../../base/popover/popover';
5
5
  import GlSprintf from '../../utilities/sprintf/sprintf';
6
+ import { badgeTypes, badgeTypeValidator } from './constants';
6
7
  import __vue_normalize__ from 'vue-runtime-helpers/dist/normalize-component.js';
7
8
 
8
9
  const i18n = {
9
- EXPERIMENT_BADGE: 'Experiment',
10
- EXPERIMENT_POPOVER_TITLE: "What's an Experiment?",
11
- EXPERIMENT_POPOVER_CONTENT: "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}",
12
- EXPERIMENT_POPOVER_BULLETS: ['May be unstable', 'Has no support and might not be documented', 'Can be removed at any time']
10
+ experiment: {
11
+ BADGE: 'Experiment',
12
+ POPOVER_TITLE: "What's an Experiment?",
13
+ POPOVER_CONTENT: "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}",
14
+ POPOVER_BULLETS: ['May be unstable', 'Has no support and might not be documented', 'Can be removed at any time']
15
+ },
16
+ beta: {
17
+ BADGE: 'Beta',
18
+ POPOVER_TITLE: "What's a Beta?",
19
+ POPOVER_CONTENT: "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}",
20
+ POPOVER_BULLETS: ['May be unstable', 'Should not cause data loss', 'Is supported by a commercially reasonable effort', 'Is complete or near completion']
21
+ }
13
22
  };
14
23
  var script = {
15
24
  name: 'GlExperimentBadge',
16
- i18n,
17
25
  components: {
18
26
  GlBadge,
19
27
  GlPopover,
@@ -24,7 +32,7 @@ var script = {
24
32
  /**
25
33
  * The URL of a page to provide more explanations on the experiment.
26
34
  */
27
- experimentHelpPageUrl: {
35
+ helpPageUrl: {
28
36
  type: String,
29
37
  required: false,
30
38
  default: ''
@@ -36,6 +44,20 @@ var script = {
36
44
  type: String,
37
45
  required: false,
38
46
  default: 'bottom'
47
+ },
48
+ /**
49
+ * The type of the badge.
50
+ */
51
+ type: {
52
+ type: String,
53
+ required: false,
54
+ default: badgeTypes[0],
55
+ validator: badgeTypeValidator
56
+ }
57
+ },
58
+ computed: {
59
+ activeType() {
60
+ return i18n[this.type];
39
61
  }
40
62
  },
41
63
  created() {
@@ -47,9 +69,9 @@ var script = {
47
69
  const __vue_script__ = script;
48
70
 
49
71
  /* template */
50
- var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('gl-badge',{staticClass:"gl-mx-4 gl-hover-cursor-pointer",attrs:{"id":_vm.triggerId,"variant":"neutral","size":"md"}},[_c('span',[_vm._v(_vm._s(_vm.$options.i18n.EXPERIMENT_BADGE))]),_vm._v(" "),_c('gl-popover',{attrs:{"triggers":"click","show-close-button":"","placement":_vm.popoverPlacement,"target":_vm.triggerId,"css-classes":['gl-z-index-9999!'],"title":_vm.$options.i18n.EXPERIMENT_POPOVER_TITLE}},[_c('gl-sprintf',{attrs:{"message":_vm.$options.i18n.EXPERIMENT_POPOVER_CONTENT},scopedSlots:_vm._u([{key:"link",fn:function(ref){
72
+ var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('gl-badge',{staticClass:"gl-mx-4 gl-hover-cursor-pointer",attrs:{"id":_vm.triggerId,"variant":"neutral","size":"md"}},[_c('span',[_vm._v(_vm._s(_vm.activeType.BADGE))]),_vm._v(" "),_c('gl-popover',{attrs:{"triggers":"click","show-close-button":"","placement":_vm.popoverPlacement,"target":_vm.triggerId,"css-classes":['gl-z-index-9999!'],"title":_vm.activeType.POPOVER_TITLE}},[_c('gl-sprintf',{attrs:{"message":_vm.activeType.POPOVER_CONTENT},scopedSlots:_vm._u([{key:"link",fn:function(ref){
51
73
  var content = ref.content;
52
- return [(_vm.experimentHelpPageUrl)?_c('gl-link',{staticClass:"gl-font-sm!",attrs:{"href":_vm.experimentHelpPageUrl,"target":"_blank"}},[_vm._v("\n "+_vm._s(content)+"\n ")]):_c('span',[_vm._v(_vm._s(content))])]}},{key:"bullets",fn:function(){return [_c('ul',{staticClass:"gl-mb-0 gl-pl-5"},_vm._l((_vm.$options.i18n.EXPERIMENT_POPOVER_BULLETS),function(item,i){return _c('li',{key:("li-" + i)},[_vm._v("\n "+_vm._s(item)+"\n ")])}),0)]},proxy:true}])})],1)],1)};
74
+ return [(_vm.helpPageUrl)?_c('gl-link',{staticClass:"gl-font-sm!",attrs:{"href":_vm.helpPageUrl,"target":"_blank"}},[_vm._v("\n "+_vm._s(content)+"\n ")]):_c('span',[_vm._v(_vm._s(content))])]}},{key:"bullets",fn:function(){return [_c('ul',{staticClass:"gl-mb-0 gl-pl-5"},_vm._l((_vm.activeType.POPOVER_BULLETS),function(item,i){return _c('li',{key:("li-" + i)},[_vm._v("\n "+_vm._s(item)+"\n ")])}),0)]},proxy:true}])})],1)],1)};
53
75
  var __vue_staticRenderFns__ = [];
54
76
 
55
77
  /* style */
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Do not edit directly
3
- * Generated on Mon, 06 Nov 2023 19:28:32 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 Mon, 06 Nov 2023 19:28:32 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 Mon, 06 Nov 2023 19:28:32 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 Mon, 06 Nov 2023 19:28:32 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 Mon, 06 Nov 2023 19:28:32 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 Mon, 06 Nov 2023 19:28:32 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.2",
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",
@@ -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>