@gitlab/ui 133.0.0 → 134.1.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.
Files changed (42) hide show
  1. package/dist/components/base/avatars_inline/avatars_inline.js +5 -1
  2. package/dist/components/base/breadcrumb/breadcrumb.js +5 -1
  3. package/dist/components/base/breadcrumb/breadcrumb_item.js +7 -1
  4. package/dist/components/base/broadcast_message/broadcast_message.js +3 -3
  5. package/dist/components/base/button/button.js +36 -19
  6. package/dist/config.js +23 -3
  7. package/dist/index.css +1 -1
  8. package/dist/index.css.map +1 -1
  9. package/dist/tokens/build/js/tokens.dark.js +1 -145
  10. package/dist/tokens/build/js/tokens.js +1 -145
  11. package/dist/utils/constants.js +12 -12
  12. package/dist/utils/string_utils.js +0 -1
  13. package/package.json +11 -11
  14. package/src/components/base/avatars_inline/avatars_inline.vue +5 -1
  15. package/src/components/base/breadcrumb/breadcrumb.vue +5 -5
  16. package/src/components/base/breadcrumb/breadcrumb_item.vue +7 -1
  17. package/src/components/base/broadcast_message/broadcast_message.vue +3 -3
  18. package/src/components/base/button/button.vue +37 -16
  19. package/src/components/utilities/sprintf/sprintf.vue +0 -1
  20. package/src/config.js +21 -2
  21. package/src/tokens/build/css/tokens.css +16 -160
  22. package/src/tokens/build/css/tokens.dark.css +16 -160
  23. package/src/tokens/build/docs/tokens-tailwind-docs.dark.json +15293 -26883
  24. package/src/tokens/build/docs/tokens-tailwind-docs.json +15293 -26883
  25. package/src/tokens/build/figma/constants.dark.json +0 -1152
  26. package/src/tokens/build/figma/constants.json +0 -1152
  27. package/src/tokens/build/figma/mode.dark.json +160 -16
  28. package/src/tokens/build/figma/mode.json +160 -16
  29. package/src/tokens/build/js/tokens.dark.js +0 -144
  30. package/src/tokens/build/js/tokens.js +0 -144
  31. package/src/tokens/build/json/tokens.dark.json +15296 -19354
  32. package/src/tokens/build/json/tokens.json +15173 -19231
  33. package/src/tokens/build/scss/_tokens.dark.scss +16 -160
  34. package/src/tokens/build/scss/_tokens.scss +16 -160
  35. package/src/tokens/build/scss/_tokens_custom_properties.scss +0 -144
  36. package/src/tokens/build/tailwind/tokens.cjs +0 -75
  37. package/src/tokens/contextual/broadcast.tokens.json +160 -16
  38. package/src/utils/constants.js +11 -11
  39. package/src/utils/string_utils.js +0 -1
  40. package/tailwind.defaults.js +0 -2
  41. package/src/tokens/constant/color.theme.tokens.json +0 -1168
  42. package/src/tokens/deprecated/deprecated.color.theme.tokens.json +0 -2248
@@ -82,6 +82,10 @@ var script = {
82
82
  32: 'lg'
83
83
  }[this.avatarSize] || 'lg';
84
84
  },
85
+ rootClass() {
86
+ // eslint-disable-next-line @gitlab/tailwind-no-interpolation
87
+ return ['gl-avatars-inline', `gl-avatars-inline-${this.badgeSize}`];
88
+ },
85
89
  badgeLabel() {
86
90
  return `+${this.hiddenAvatars.length}`;
87
91
  },
@@ -104,7 +108,7 @@ var script = {
104
108
  const __vue_script__ = script;
105
109
 
106
110
  /* template */
107
- var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:"gl-avatars-inline",class:("gl-avatars-inline-" + _vm.badgeSize)},[_vm._l((_vm.visibleAvatars),function(avatar,index){return _c('div',{key:index,staticClass:"gl-avatars-inline-child"},[_vm._t("avatar",function(){return [_c('gl-avatar',_vm._b({attrs:{"size":_vm.avatarSize}},'gl-avatar',avatar,false))]},{"avatar":avatar})],2)}),_vm._v(" "),(_vm.collapsed && _vm.collapsable)?_c('div',{staticClass:"gl-avatars-inline-child"},[(_vm.badgeTooltipProp)?_c('gl-tooltip',{attrs:{"target":function () { return _vm.$refs.badge; }}},[_vm._v("\n "+_vm._s(_vm.badgeTooltipTitle)+"\n ")]):_vm._e(),_vm._v(" "),_c('span',{ref:"badge",class:['gl-avatars-inline-badge', _vm.badgeSize],attrs:{"data-testid":"collapsed-avatars-badge","aria-hidden":"true"}},[_vm._v("\n "+_vm._s(_vm.badgeLabel)+"\n ")]),_vm._v(" "),_c('span',{staticClass:"gl-sr-only",attrs:{"data-testid":"badge-sr-only-text"}},[_vm._v(_vm._s(_vm.badgeSrOnlyText))])],1):_vm._e()],2)};
111
+ var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{class:_vm.rootClass},[_vm._l((_vm.visibleAvatars),function(avatar,index){return _c('div',{key:index,staticClass:"gl-avatars-inline-child"},[_vm._t("avatar",function(){return [_c('gl-avatar',_vm._b({attrs:{"size":_vm.avatarSize}},'gl-avatar',avatar,false))]},{"avatar":avatar})],2)}),_vm._v(" "),(_vm.collapsed && _vm.collapsable)?_c('div',{staticClass:"gl-avatars-inline-child"},[(_vm.badgeTooltipProp)?_c('gl-tooltip',{attrs:{"target":function () { return _vm.$refs.badge; }}},[_vm._v("\n "+_vm._s(_vm.badgeTooltipTitle)+"\n ")]):_vm._e(),_vm._v(" "),_c('span',{ref:"badge",class:['gl-avatars-inline-badge', _vm.badgeSize],attrs:{"data-testid":"collapsed-avatars-badge","aria-hidden":"true"}},[_vm._v("\n "+_vm._s(_vm.badgeLabel)+"\n ")]),_vm._v(" "),_c('span',{staticClass:"gl-sr-only",attrs:{"data-testid":"badge-sr-only-text"}},[_vm._v(_vm._s(_vm.badgeSrOnlyText))])],1):_vm._e()],2)};
108
112
  var __vue_staticRenderFns__ = [];
109
113
 
110
114
  /* style */
@@ -128,6 +128,10 @@ var script = {
128
128
  }
129
129
  return '';
130
130
  },
131
+ dropdownItemClass() {
132
+ // eslint-disable-next-line @gitlab/tailwind-no-interpolation
133
+ return ['gl-breadcrumb-item', `gl-breadcrumb-item-${this.size}`];
134
+ },
131
135
  dropdownSize() {
132
136
  return this.size === 'sm' ? 'small' : 'medium';
133
137
  },
@@ -247,7 +251,7 @@ var script = {
247
251
  const __vue_script__ = script;
248
252
 
249
253
  /* template */
250
- var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('nav',{staticClass:"gl-breadcrumbs",style:(_vm.breadcrumbStyle),attrs:{"aria-label":_vm.ariaLabel}},[_c('ol',_vm._g(_vm._b({staticClass:"gl-breadcrumb-list breadcrumb"},'ol',_vm.$attrs,false),_vm.$listeners),[(_vm.hasCollapsible || !_vm.resizeDone)?_c('li',{ref:"dropdown",class:("gl-breadcrumb-item gl-breadcrumb-item-" + _vm.size)},[_c('gl-disclosure-dropdown',{attrs:{"items":_vm.overflowingItems,"toggle-text":_vm.showMoreLabel,"fluid-width":"","text-sr-only":"","no-caret":"","icon":"ellipsis_h","size":_vm.dropdownSize}})],1):_vm._e(),_vm._v(" "),_vm._l((_vm.fittingItems),function(item,index){return _c('gl-breadcrumb-item',{key:index,ref:"breadcrumbs",refInFor:true,class:_vm.itemClass,attrs:{"text":item.text,"href":item.href,"to":item.to,"size":_vm.size,"aria-current":_vm.getAriaCurrentAttr(index)},scopedSlots:_vm._u([{key:"default",fn:function(){return [(item.avatarPath)?_c('gl-avatar',{staticClass:"gl-breadcrumb-avatar-tile gl-border gl-mr-2",attrs:{"src":item.avatarPath,"size":_vm.avatarSize,"aria-hidden":"true","shape":"rect","data-testid":"avatar"}}):_vm._e(),_c('span',{staticClass:"gl-align-middle"},[_vm._v(_vm._s(item.text))])]},proxy:true}],null,true)})}),_vm._v(" "),(_vm.showClipboardButton)?_c('li',{staticClass:"gl-breadcrumb-clipboard-button"},[_c('clipboard-button',_vm._b({ref:"clipboardButton",staticClass:"gl-ml-2",attrs:{"data-testid":"copy-to-clipboard-button","text":_vm.clipboardButtonText,"size":_vm.dropdownSize}},'clipboard-button',_vm.clipboardTooltipText ? { title: _vm.clipboardTooltipText } : {},false))],1):_vm._e()],2)])};
254
+ var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('nav',{staticClass:"gl-breadcrumbs",style:(_vm.breadcrumbStyle),attrs:{"aria-label":_vm.ariaLabel}},[_c('ol',_vm._g(_vm._b({staticClass:"gl-breadcrumb-list breadcrumb"},'ol',_vm.$attrs,false),_vm.$listeners),[(_vm.hasCollapsible || !_vm.resizeDone)?_c('li',{ref:"dropdown",class:_vm.dropdownItemClass},[_c('gl-disclosure-dropdown',{attrs:{"items":_vm.overflowingItems,"toggle-text":_vm.showMoreLabel,"fluid-width":"","text-sr-only":"","no-caret":"","icon":"ellipsis_h","size":_vm.dropdownSize}})],1):_vm._e(),_vm._v(" "),_vm._l((_vm.fittingItems),function(item,index){return _c('gl-breadcrumb-item',{key:index,ref:"breadcrumbs",refInFor:true,class:_vm.itemClass,attrs:{"text":item.text,"href":item.href,"to":item.to,"size":_vm.size,"aria-current":_vm.getAriaCurrentAttr(index)},scopedSlots:_vm._u([{key:"default",fn:function(){return [(item.avatarPath)?_c('gl-avatar',{staticClass:"gl-breadcrumb-avatar-tile gl-border gl-mr-2",attrs:{"src":item.avatarPath,"size":_vm.avatarSize,"aria-hidden":"true","shape":"rect","data-testid":"avatar"}}):_vm._e(),_c('span',{staticClass:"gl-align-middle"},[_vm._v(_vm._s(item.text))])]},proxy:true}],null,true)})}),_vm._v(" "),(_vm.showClipboardButton)?_c('li',{staticClass:"gl-breadcrumb-clipboard-button"},[_c('clipboard-button',_vm._b({ref:"clipboardButton",staticClass:"gl-ml-2",attrs:{"data-testid":"copy-to-clipboard-button","text":_vm.clipboardButtonText,"size":_vm.dropdownSize}},'clipboard-button',_vm.clipboardTooltipText ? { title: _vm.clipboardTooltipText } : {},false))],1):_vm._e()],2)])};
251
255
  var __vue_staticRenderFns__ = [];
252
256
 
253
257
  /* style */
@@ -54,6 +54,12 @@ var script = {
54
54
  validator: value => Object.keys(breadCrumbSizeOptions).includes(value)
55
55
  }
56
56
  },
57
+ computed: {
58
+ itemClass() {
59
+ // eslint-disable-next-line @gitlab/tailwind-no-interpolation
60
+ return ['gl-breadcrumb-item', `gl-breadcrumb-item-${this.size}`];
61
+ }
62
+ },
57
63
  linkVariantUnstyled
58
64
  };
59
65
 
@@ -61,7 +67,7 @@ var script = {
61
67
  const __vue_script__ = script;
62
68
 
63
69
  /* template */
64
- var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('li',{class:("gl-breadcrumb-item gl-breadcrumb-item-" + _vm.size)},[_c('gl-link',{attrs:{"href":_vm.href,"to":_vm.to,"aria-current":_vm.ariaCurrent,"variant":_vm.$options.linkVariantUnstyled}},[_vm._t("default",function(){return [_vm._v(_vm._s(_vm.text))]})],2)],1)};
70
+ var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('li',{class:_vm.itemClass},[_c('gl-link',{attrs:{"href":_vm.href,"to":_vm.to,"aria-current":_vm.ariaCurrent,"variant":_vm.$options.linkVariantUnstyled}},[_vm._t("default",function(){return [_vm._v(_vm._s(_vm.text))]})],2)],1)};
65
71
  var __vue_staticRenderFns__ = [];
66
72
 
67
73
  /* style */
@@ -1,4 +1,4 @@
1
- import { colorThemes } from '../../../utils/constants';
1
+ import { broadcastMessageThemes } from '../../../utils/constants';
2
2
  import { translate } from '../../../utils/i18n';
3
3
  import CloseButton from '../../shared_components/close_button/close_button';
4
4
  import GlIcon from '../icon/icon';
@@ -42,8 +42,8 @@ var script = {
42
42
  theme: {
43
43
  type: String,
44
44
  required: false,
45
- default: Object.keys(colorThemes)[0],
46
- validator: value => Object.keys(colorThemes).includes(value)
45
+ default: Object.keys(broadcastMessageThemes)[0],
46
+ validator: value => Object.keys(broadcastMessageThemes).includes(value)
47
47
  },
48
48
  /**
49
49
  * The base layout to use. `notification` type broadcast messages are not compatible
@@ -3,7 +3,7 @@ import { buttonCategoryOptions, buttonVariantOptions, buttonSizeOptions, linkVar
3
3
  import { logWarning, stopEvent } from '../../../utils/utils';
4
4
  import { isSlotEmpty } from '../../../utils/is_slot_empty';
5
5
  import { SafeLinkMixin } from '../../mixins/safe_link_mixin';
6
- import { isEvent } from '../../../vendor/bootstrap-vue/src/utils/inspect';
6
+ import { glButtonConfig } from '../../../config';
7
7
  import GlIcon from '../icon/icon';
8
8
  import GlLoadingIcon from '../loading_icon/loading_icon';
9
9
  import { SPACE, ENTER } from '../new_dropdowns/constants';
@@ -117,6 +117,14 @@ var script = {
117
117
  required: false,
118
118
  default: false
119
119
  },
120
+ /**
121
+ * Keep the button accessible while `disabled` is `true`. Uses `aria-disabled` so the element remains focusable and is announced by assistive technology.
122
+ */
123
+ accessibleDisabled: {
124
+ type: Boolean,
125
+ required: false,
126
+ default: () => glButtonConfig.accessibleDisabledButton
127
+ },
120
128
  /**
121
129
  * Denotes the target URL of the link for standard links.
122
130
  */
@@ -232,9 +240,20 @@ var script = {
232
240
  hasIconOnly() {
233
241
  return isSlotEmpty(this, 'default') && this.hasIcon && this.count == null;
234
242
  },
235
- isButtonAriaDisabled() {
243
+ isDisabledOrLoading() {
244
+ if (this.accessibleDisabled) {
245
+ return this.disabled || this.isButton && this.loading;
246
+ }
236
247
  return this.isButton && this.loading;
237
248
  },
249
+ ariaDisabled() {
250
+ if (this.isDisabledOrLoading) return 'true';
251
+ // Non-standard tags need an explicit aria-disabled value to convey interactive state.
252
+ if (this.isNonStandardTag) {
253
+ return this.accessibleDisabled ? 'false' : String(this.disabled);
254
+ }
255
+ return null;
256
+ },
238
257
  buttonClasses() {
239
258
  const classes = ['btn', 'gl-button', `btn-${this.variant}`, `btn-${this.buttonSize}`];
240
259
  if (this.category !== buttonCategoryOptions.primary) {
@@ -245,7 +264,7 @@ var script = {
245
264
  'button-ellipsis-horizontal': this.hasIconOnly && this.icon === 'ellipsis_h',
246
265
  selected: this.selected,
247
266
  'btn-block': this.displayBlock,
248
- disabled: this.disabled || this.isButtonAriaDisabled
267
+ disabled: this.disabled || this.isDisabledOrLoading
249
268
  });
250
269
  if (this.label) {
251
270
  classes.push('btn', 'btn-label');
@@ -274,12 +293,12 @@ var script = {
274
293
  return !this.isLink && !this.isButton;
275
294
  },
276
295
  tabindex() {
277
- // When disabled remove links and non-standard tags from tab order
278
- if (this.disabled) {
296
+ // Legacy: remove disabled links and non-standard tags from tab order.
297
+ if (!this.accessibleDisabled && this.disabled) {
279
298
  return this.isLink || this.isNonStandardTag ? '-1' : this.$attrs.tabindex;
280
299
  }
281
-
282
- // Add hash links and non-standard tags to tab order
300
+ // Inactive elements stay in tab order so assistive technology can discover them;
301
+ // aria-disabled communicates the inactive state instead of removing the element.
283
302
  return this.isNonStandardTag || this.isHashLink ? '0' : this.$attrs.tabindex;
284
303
  },
285
304
  computedPropsAndAttributes() {
@@ -287,18 +306,15 @@ var script = {
287
306
  const base = {
288
307
  // Type only used for "real" buttons
289
308
  type: this.isButton ? this.type : null,
290
- // Disabled only set on "real" buttons
291
- disabled: this.isButton ? this.disabled : null,
309
+ // Legacy: native disabled attribute on real buttons.
310
+ ...(!this.accessibleDisabled && this.isButton ? {
311
+ disabled: this.disabled
312
+ } : {}),
292
313
  // We add a role of button when the tag is not a link or button or when link has `href` of `#`
293
314
  role: this.isNonStandardTag || this.isHashLink ? 'button' : (_this$$attrs = this.$attrs) === null || _this$$attrs === void 0 ? void 0 : _this$$attrs.role,
294
- // We set the `aria-disabled` state for non-standard tags
295
- ...(this.isNonStandardTag ? {
296
- 'aria-disabled': String(this.disabled)
297
- } : {}),
298
315
  tabindex: this.tabindex,
299
- // We set the `aria-disabled` state for buttons while loading
300
- ...(this.isButtonAriaDisabled ? {
301
- 'aria-disabled': 'true'
316
+ ...(this.ariaDisabled !== null ? {
317
+ 'aria-disabled': this.ariaDisabled
302
318
  } : {})
303
319
  };
304
320
  if (this.isLink) {
@@ -328,7 +344,7 @@ var script = {
328
344
  const listeners = {
329
345
  ...this.$listeners
330
346
  };
331
- if (this.isButtonAriaDisabled) {
347
+ if (this.isDisabledOrLoading) {
332
348
  delete listeners.click;
333
349
  }
334
350
  return listeners;
@@ -359,7 +375,7 @@ var script = {
359
375
  // Skip if disabled
360
376
  // Add SPACE keydown handler for link has `href` of `#`
361
377
  // Add ENTER handler for non-standard tags
362
- if (!this.disabled && (this.isNonStandardTag || this.isHashLink)) {
378
+ if (!this.disabled && !this.isDisabledOrLoading && (this.isNonStandardTag || this.isHashLink)) {
363
379
  const code = event.code;
364
380
  if (code === SPACE || code === ENTER && this.isNonStandardTag) {
365
381
  const target = event.currentTarget || event.target;
@@ -371,7 +387,8 @@ var script = {
371
387
  }
372
388
  },
373
389
  maybeStopEvent(event) {
374
- if (this.isButtonAriaDisabled && isEvent(event)) {
390
+ const eventIsEvent = event instanceof Event;
391
+ if (this.isDisabledOrLoading && eventIsEvent) {
375
392
  stopEvent(event);
376
393
  }
377
394
  }
package/dist/config.js CHANGED
@@ -4,6 +4,7 @@ const i18n = translationKeys;
4
4
  const defaultConfig = {
5
5
  firstDayOfWeek: 0 // Defaults to 0 (Sunday)
6
6
  };
7
+ const glButtonConfig = {};
7
8
  let configured = false;
8
9
 
9
10
  /**
@@ -13,13 +14,15 @@ let configured = false;
13
14
  * @template TValue=string
14
15
  * @property {undefined | Object} translations Generic translations for component labels to fall back to.
15
16
  * @property {undefined | Number} firstDayOfWeek Configured first day of the week, from 0 (Sunday) to 6 (Saturday).
16
- * @property {boolean} [accessibleLoadingButton] Temporary flag to enable accessible loading button.
17
+ * @property {boolean} [accessibleDisabledButton] Temporary flag to enable the accessible disabled button.
17
18
  *
18
19
  */
19
20
  const setConfigs = function () {
20
21
  let _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
21
22
  translations = _ref.translations,
22
- firstDayOfWeek = _ref.firstDayOfWeek;
23
+ firstDayOfWeek = _ref.firstDayOfWeek,
24
+ _ref$accessibleDisabl = _ref.accessibleDisabledButton,
25
+ accessibleDisabledButton = _ref$accessibleDisabl === void 0 ? false : _ref$accessibleDisabl;
23
26
  if (configured) {
24
27
  if (process.env.NODE_ENV === 'development') {
25
28
  throw new Error('GitLab UI can only be configured once!');
@@ -47,6 +50,23 @@ const setConfigs = function () {
47
50
  }
48
51
  Object.assign(i18n, translations);
49
52
  }
53
+
54
+ // Temporary flag to enable the accessible disabled button feature.
55
+ // This flag allows the feature to be opt-in during the rollout phase,
56
+ // giving us the flexibility to test and validate its impact on user experience.
57
+
58
+ // The global variable `accessibleDisabledButton` is set to a boolean value
59
+ // to indicate whether the button should use aria-disabled while disabled.
60
+
61
+ // Future Plan:
62
+ // Once the accessible disabled button feature is validated and stable,
63
+ // we will remove this temporary flag and make the feature the default behavior.
64
+ // At that point, there will be no need for opt-in or opt-out mechanisms for this feature.
65
+ if (typeof accessibleDisabledButton === 'boolean') {
66
+ Object.assign(glButtonConfig, {
67
+ accessibleDisabledButton
68
+ });
69
+ }
50
70
  };
51
71
 
52
- export { setConfigs as default, defaultConfig, i18n };
72
+ export { setConfigs as default, defaultConfig, glButtonConfig, i18n };