@gitlab/ui 130.1.0 → 130.2.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 (23) hide show
  1. package/dist/components/base/button/button.js +1 -2
  2. package/dist/components/base/new_dropdowns/base_dropdown/base_dropdown.js +9 -0
  3. package/dist/components/base/new_dropdowns/disclosure/disclosure_dropdown.js +18 -2
  4. package/dist/vendor/bootstrap-vue/src/mixins/dropdown.js +46 -11
  5. package/dist/vendor/bootstrap-vue/src/mixins/form-control.js +30 -7
  6. package/dist/vendor/bootstrap-vue/src/mixins/form-custom.js +5 -2
  7. package/dist/vendor/bootstrap-vue/src/mixins/form-options.js +26 -7
  8. package/dist/vendor/bootstrap-vue/src/mixins/form-size.js +5 -2
  9. package/dist/vendor/bootstrap-vue/src/mixins/form-state.js +5 -2
  10. package/dist/vendor/bootstrap-vue/src/mixins/form-text.js +56 -13
  11. package/dist/vendor/bootstrap-vue/src/mixins/id.js +5 -2
  12. package/package.json +5 -2
  13. package/src/components/base/button/button.vue +1 -2
  14. package/src/components/base/new_dropdowns/base_dropdown/base_dropdown.vue +9 -0
  15. package/src/components/base/new_dropdowns/disclosure/disclosure_dropdown.vue +23 -1
  16. package/src/vendor/bootstrap-vue/src/mixins/dropdown.js +46 -11
  17. package/src/vendor/bootstrap-vue/src/mixins/form-control.js +30 -7
  18. package/src/vendor/bootstrap-vue/src/mixins/form-custom.js +5 -2
  19. package/src/vendor/bootstrap-vue/src/mixins/form-options.js +26 -7
  20. package/src/vendor/bootstrap-vue/src/mixins/form-size.js +5 -2
  21. package/src/vendor/bootstrap-vue/src/mixins/form-state.js +5 -2
  22. package/src/vendor/bootstrap-vue/src/mixins/form-text.js +56 -13
  23. package/src/vendor/bootstrap-vue/src/mixins/id.js +5 -2
@@ -347,8 +347,7 @@ var script = {
347
347
  }
348
348
  },
349
349
  mounted() {
350
- // eslint-disable-next-line @gitlab/vue-prefer-dollar-scopedslots
351
- if (!this.$slots.default && !this.$attrs['aria-label'] && !this.$props.label) {
350
+ if (!('default' in this.$scopedSlots) && !this.$attrs['aria-label'] && !this.label) {
352
351
  logWarning('Accessible name missing. Please add inner text or aria-label.', {
353
352
  name: 'GlButton',
354
353
  element: this.$el
@@ -163,6 +163,14 @@ var script = {
163
163
  required: false,
164
164
  default: null
165
165
  },
166
+ /**
167
+ * The `aria-label` attribute value for the toggle `button`.
168
+ */
169
+ ariaLabel: {
170
+ type: String,
171
+ required: false,
172
+ default: null
173
+ },
166
174
  /**
167
175
  * Custom value to be passed to the offset middleware.
168
176
  * https://floating-ui.com/docs/offset
@@ -273,6 +281,7 @@ var script = {
273
281
  'aria-expanded': String(this.visible),
274
282
  'aria-haspopup': this.ariaHaspopup,
275
283
  'aria-labelledby': this.toggleLabelledBy,
284
+ 'aria-label': this.ariaLabel || undefined,
276
285
  'aria-activedescendant': this.ariaActiveDescendant
277
286
  };
278
287
  },
@@ -1,5 +1,5 @@
1
1
  import { uniqueId, clamp } from 'lodash-es';
2
- import { stopEvent, filterVisible } from '../../../../utils/utils';
2
+ import { logWarning, stopEvent, filterVisible } from '../../../../utils/utils';
3
3
  import { GL_DROPDOWN_SHOWN, GL_DROPDOWN_HIDDEN, GL_DROPDOWN_BEFORE_CLOSE, GL_DROPDOWN_FOCUS_CONTENT, POSITION_ABSOLUTE, POSITION_FIXED, HOME, END, ARROW_UP, ARROW_DOWN, ENTER, SPACE, GL_DROPDOWN_CONTENTS_CLASS } from '../constants';
4
4
  import { buttonCategoryOptions, dropdownVariantOptions, buttonSizeOptions, dropdownPlacements } from '../../../../utils/constants';
5
5
  import GlBaseDropdown from '../base_dropdown/base_dropdown';
@@ -143,6 +143,17 @@ var script = {
143
143
  required: false,
144
144
  default: null
145
145
  },
146
+ /**
147
+ * The `aria-label` attribute value for the toggle button.
148
+ * Use when there is no visible label element to reference with `toggleAriaLabelledBy`.
149
+ * Do not provide both `toggleAriaLabel` and `toggleAriaLabelledBy`.
150
+ * When both are present, `toggleAriaLabelledBy` takes precedence per the WAI-ARIA spec.
151
+ */
152
+ toggleAriaLabel: {
153
+ type: String,
154
+ required: false,
155
+ default: null
156
+ },
146
157
  /**
147
158
  * The `aria-labelledby` attribute value for the list of options
148
159
  * Provide the string of ids seperated by space
@@ -230,6 +241,11 @@ var script = {
230
241
  }
231
242
  },
232
243
  mounted() {
244
+ if (this.toggleAriaLabel && this.toggleAriaLabelledBy) {
245
+ logWarning('Do not provide both `toggleAriaLabel` and `toggleAriaLabelledBy`. ' + 'When both are present, `toggleAriaLabelledBy` takes precedence and `toggleAriaLabel` is ignored. ' + 'See https://design.gitlab.com/components/dropdown-disclosure/#accessibility', {
246
+ name: 'GlDisclosureDropdown'
247
+ });
248
+ }
233
249
  if (this.startOpened) {
234
250
  this.open();
235
251
  }
@@ -349,7 +365,7 @@ var script = {
349
365
  const __vue_script__ = script;
350
366
 
351
367
  /* template */
352
- var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('gl-base-dropdown',{ref:"baseDropdown",staticClass:"gl-disclosure-dropdown",attrs:{"aria-labelledby":_vm.toggleAriaLabelledBy,"arrow-element":_vm.$refs.disclosureArrow,"toggle-id":_vm.toggleId,"toggle-text":_vm.toggleText,"toggle-class":_vm.toggleClass,"text-sr-only":_vm.textSrOnly,"category":_vm.category,"variant":_vm.variant,"size":_vm.size,"icon":_vm.icon,"disabled":_vm.disabled,"loading":_vm.loading,"no-caret":_vm.noCaret,"placement":_vm.placement,"block":_vm.block,"offset":_vm.dropdownOffset,"fluid-width":_vm.fluidWidth,"positioning-strategy":_vm.positioningStrategy,"is-disclosure":""},on:_vm._d({},[_vm.$options.events.GL_DROPDOWN_SHOWN,_vm.onShow,_vm.$options.events.GL_DROPDOWN_HIDDEN,_vm.onHide,_vm.$options.events.GL_DROPDOWN_BEFORE_CLOSE,_vm.onBeforeClose,_vm.$options.events.GL_DROPDOWN_FOCUS_CONTENT,_vm.onKeydown]),scopedSlots:_vm._u([(_vm.hasCustomToggle)?{key:"toggle",fn:function(slotProps){return [_vm._t("toggle",null,null,slotProps)]}}:null],null,true)},[_vm._v(" "),_vm._t("header"),_vm._v(" "),_c(_vm.disclosureTag,{ref:"content",tag:"component",class:_vm.$options.GL_DROPDOWN_CONTENTS_CLASS,attrs:{"id":_vm.disclosureId,"aria-labelledby":_vm.listAriaLabelledBy || _vm.toggleId,"data-testid":"disclosure-content","tabindex":"-1"},on:{"keydown":_vm.onKeydown,"click":_vm.handleAutoClose}},[_vm._t("default",function(){return [_vm._l((_vm.items),function(item,index){return [(_vm.isItem(item))?[_c('gl-disclosure-dropdown-item',{key:_vm.uniqueItemId(),attrs:{"siblings-have-icons":_vm.siblingsHaveIcons,"item":item},on:{"action":_vm.handleAction},scopedSlots:_vm._u([('list-item' in _vm.$scopedSlots)?{key:"list-item",fn:function(){return [_vm._t("list-item",null,{"item":item})]},proxy:true}:null],null,true)})]:[_c('gl-disclosure-dropdown-group',{key:item.name,attrs:{"bordered":index !== 0,"group":item},on:{"action":_vm.handleAction},scopedSlots:_vm._u([(_vm.$scopedSlots['group-label'])?{key:"group-label",fn:function(){return [_vm._t("group-label",null,{"group":item})]},proxy:true}:null,(_vm.$scopedSlots['list-item'])?{key:"default",fn:function(){return _vm._l((item.items),function(groupItem){return _c('gl-disclosure-dropdown-item',{key:_vm.uniqueItemId(),attrs:{"siblings-have-icons":_vm.doSomeItemsHaveIcon(item.items),"item":groupItem},on:{"action":_vm.handleAction},scopedSlots:_vm._u([{key:"list-item",fn:function(){return [_vm._t("list-item",null,{"item":groupItem})]},proxy:true}],null,true)})})},proxy:true}:null],null,true)})]]})]})],2),_vm._v(" "),_vm._t("footer")],2)};
368
+ var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('gl-base-dropdown',{ref:"baseDropdown",staticClass:"gl-disclosure-dropdown",attrs:{"aria-labelledby":_vm.toggleAriaLabelledBy,"aria-label":_vm.toggleAriaLabelledBy ? undefined : _vm.toggleAriaLabel,"arrow-element":_vm.$refs.disclosureArrow,"toggle-id":_vm.toggleId,"toggle-text":_vm.toggleText,"toggle-class":_vm.toggleClass,"text-sr-only":_vm.textSrOnly,"category":_vm.category,"variant":_vm.variant,"size":_vm.size,"icon":_vm.icon,"disabled":_vm.disabled,"loading":_vm.loading,"no-caret":_vm.noCaret,"placement":_vm.placement,"block":_vm.block,"offset":_vm.dropdownOffset,"fluid-width":_vm.fluidWidth,"positioning-strategy":_vm.positioningStrategy,"is-disclosure":""},on:_vm._d({},[_vm.$options.events.GL_DROPDOWN_SHOWN,_vm.onShow,_vm.$options.events.GL_DROPDOWN_HIDDEN,_vm.onHide,_vm.$options.events.GL_DROPDOWN_BEFORE_CLOSE,_vm.onBeforeClose,_vm.$options.events.GL_DROPDOWN_FOCUS_CONTENT,_vm.onKeydown]),scopedSlots:_vm._u([(_vm.hasCustomToggle)?{key:"toggle",fn:function(slotProps){return [_vm._t("toggle",null,null,slotProps)]}}:null],null,true)},[_vm._v(" "),_vm._t("header"),_vm._v(" "),_c(_vm.disclosureTag,{ref:"content",tag:"component",class:_vm.$options.GL_DROPDOWN_CONTENTS_CLASS,attrs:{"id":_vm.disclosureId,"aria-labelledby":_vm.listAriaLabelledBy || _vm.toggleId,"data-testid":"disclosure-content","tabindex":"-1"},on:{"keydown":_vm.onKeydown,"click":_vm.handleAutoClose}},[_vm._t("default",function(){return [_vm._l((_vm.items),function(item,index){return [(_vm.isItem(item))?[_c('gl-disclosure-dropdown-item',{key:_vm.uniqueItemId(),attrs:{"siblings-have-icons":_vm.siblingsHaveIcons,"item":item},on:{"action":_vm.handleAction},scopedSlots:_vm._u([('list-item' in _vm.$scopedSlots)?{key:"list-item",fn:function(){return [_vm._t("list-item",null,{"item":item})]},proxy:true}:null],null,true)})]:[_c('gl-disclosure-dropdown-group',{key:item.name,attrs:{"bordered":index !== 0,"group":item},on:{"action":_vm.handleAction},scopedSlots:_vm._u([(_vm.$scopedSlots['group-label'])?{key:"group-label",fn:function(){return [_vm._t("group-label",null,{"group":item})]},proxy:true}:null,(_vm.$scopedSlots['list-item'])?{key:"default",fn:function(){return _vm._l((item.items),function(groupItem){return _c('gl-disclosure-dropdown-item',{key:_vm.uniqueItemId(),attrs:{"siblings-have-icons":_vm.doSomeItemsHaveIcon(item.items),"item":groupItem},on:{"action":_vm.handleAction},scopedSlots:_vm._u([{key:"list-item",fn:function(){return [_vm._t("list-item",null,{"item":groupItem})]},proxy:true}],null,true)})})},proxy:true}:null],null,true)})]]})]})],2),_vm._v(" "),_vm._t("footer")],2)};
353
369
  var __vue_staticRenderFns__ = [];
354
370
 
355
371
  /* style */
@@ -4,13 +4,12 @@ import { NAME_DROPDOWN } from '../constants/components';
4
4
  import { EVENT_NAME_SHOWN, EVENT_NAME_HIDDEN, EVENT_NAME_TOGGLE, EVENT_NAME_CLICK, EVENT_NAME_SHOW, EVENT_NAME_HIDE } from '../constants/events';
5
5
  import { CODE_ENTER, CODE_SPACE, CODE_DOWN, CODE_ESC, CODE_UP } from '../constants/key-codes';
6
6
  import { PLACEMENT_TOP_END, PLACEMENT_TOP_START, PLACEMENT_BOTTOM_START, PLACEMENT_RIGHT_START, PLACEMENT_LEFT_START, PLACEMENT_BOTTOM_END } from '../constants/popper';
7
- import { PROP_TYPE_STRING, PROP_TYPE_BOOLEAN, PROP_TYPE_NUMBER_STRING, PROP_TYPE_OBJECT } from '../constants/props';
7
+ import { PROP_TYPE_STRING, PROP_TYPE_BOOLEAN, PROP_TYPE_NUMBER, PROP_TYPE_OBJECT } from '../constants/props';
8
8
  import { HTMLElement } from '../constants/safe-types';
9
9
  import { BvEvent } from '../utils/bv-event.class';
10
10
  import { requestAF, contains, closest, attemptFocus, selectAll, isVisible } from '../utils/dom';
11
11
  import { getRootEventName, stopEvent } from '../utils/events';
12
12
  import { sortKeys, mergeDeep } from '../utils/object';
13
- import { makeProp } from '../utils/props';
14
13
  import { warn } from '../utils/warn';
15
14
  import { clickOutMixin } from './click-out';
16
15
  import { focusInMixin } from './focus-in';
@@ -38,22 +37,58 @@ const props = sortKeys({
38
37
  ...props$1,
39
38
  // String: `scrollParent`, `window` or `viewport`
40
39
  // HTMLElement: HTML Element reference
41
- boundary: makeProp([HTMLElement, PROP_TYPE_STRING], 'scrollParent'),
42
- disabled: makeProp(PROP_TYPE_BOOLEAN, false),
40
+ boundary: {
41
+ type: [HTMLElement, PROP_TYPE_STRING],
42
+ required: false,
43
+ default: 'scrollParent'
44
+ },
45
+ disabled: {
46
+ type: PROP_TYPE_BOOLEAN,
47
+ required: false,
48
+ default: false
49
+ },
43
50
  // Place left if possible
44
- dropleft: makeProp(PROP_TYPE_BOOLEAN, false),
51
+ dropleft: {
52
+ type: PROP_TYPE_BOOLEAN,
53
+ required: false,
54
+ default: false
55
+ },
45
56
  // Place right if possible
46
- dropright: makeProp(PROP_TYPE_BOOLEAN, false),
57
+ dropright: {
58
+ type: PROP_TYPE_BOOLEAN,
59
+ required: false,
60
+ default: false
61
+ },
47
62
  // Place on top if possible
48
- dropup: makeProp(PROP_TYPE_BOOLEAN, false),
63
+ dropup: {
64
+ type: PROP_TYPE_BOOLEAN,
65
+ required: false,
66
+ default: false
67
+ },
49
68
  // Disable auto-flipping of menu from bottom <=> top
50
- noFlip: makeProp(PROP_TYPE_BOOLEAN, false),
69
+ noFlip: {
70
+ type: PROP_TYPE_BOOLEAN,
71
+ required: false,
72
+ default: false
73
+ },
51
74
  // Number of pixels or a CSS unit value to offset menu
52
75
  // (i.e. `1px`, `1rem`, etc.)
53
- offset: makeProp(PROP_TYPE_NUMBER_STRING, 0),
54
- popperOpts: makeProp(PROP_TYPE_OBJECT, {}),
76
+ offset: {
77
+ type: [PROP_TYPE_NUMBER, PROP_TYPE_STRING],
78
+ required: false,
79
+ default: 0
80
+ },
81
+ popperOpts: {
82
+ type: PROP_TYPE_OBJECT,
83
+ required: false,
84
+ default: () => ({})
85
+ },
55
86
  // Right align menu (default is left align)
56
- right: makeProp(PROP_TYPE_BOOLEAN, false)
87
+ right: {
88
+ type: PROP_TYPE_BOOLEAN,
89
+ required: false,
90
+ default: false
91
+ }
57
92
  });
58
93
 
59
94
  // --- Mixin ---
@@ -1,7 +1,6 @@
1
1
  import { extend } from '../vue';
2
2
  import { PROP_TYPE_BOOLEAN, PROP_TYPE_STRING } from '../constants/props';
3
3
  import { requestAF, isVisible, matches, select, attemptFocus } from '../utils/dom';
4
- import { makeProp } from '../utils/props';
5
4
 
6
5
  // --- Constants ---
7
6
 
@@ -10,12 +9,36 @@ const SELECTOR = 'input, textarea, select';
10
9
  // --- Props ---
11
10
 
12
11
  const props = {
13
- autofocus: makeProp(PROP_TYPE_BOOLEAN, false),
14
- disabled: makeProp(PROP_TYPE_BOOLEAN, false),
15
- form: makeProp(PROP_TYPE_STRING),
16
- id: makeProp(PROP_TYPE_STRING),
17
- name: makeProp(PROP_TYPE_STRING),
18
- required: makeProp(PROP_TYPE_BOOLEAN, false)
12
+ autofocus: {
13
+ type: PROP_TYPE_BOOLEAN,
14
+ required: false,
15
+ default: false
16
+ },
17
+ disabled: {
18
+ type: PROP_TYPE_BOOLEAN,
19
+ required: false,
20
+ default: false
21
+ },
22
+ form: {
23
+ type: PROP_TYPE_STRING,
24
+ required: false,
25
+ default: undefined
26
+ },
27
+ id: {
28
+ type: PROP_TYPE_STRING,
29
+ required: false,
30
+ default: undefined
31
+ },
32
+ name: {
33
+ type: PROP_TYPE_STRING,
34
+ required: false,
35
+ default: undefined
36
+ },
37
+ required: {
38
+ type: PROP_TYPE_BOOLEAN,
39
+ required: false,
40
+ default: false
41
+ }
19
42
  };
20
43
 
21
44
  // --- Mixin ---
@@ -1,11 +1,14 @@
1
1
  import { extend } from '../vue';
2
2
  import { PROP_TYPE_BOOLEAN } from '../constants/props';
3
- import { makeProp } from '../utils/props';
4
3
 
5
4
  // --- Props ---
6
5
 
7
6
  const props = {
8
- plain: makeProp(PROP_TYPE_BOOLEAN, false)
7
+ plain: {
8
+ type: PROP_TYPE_BOOLEAN,
9
+ required: false,
10
+ default: false
11
+ }
9
12
  };
10
13
 
11
14
  // --- Mixin ---
@@ -1,10 +1,9 @@
1
1
  import { extend } from '../vue';
2
- import { PROP_TYPE_STRING, PROP_TYPE_ARRAY_OBJECT } from '../constants/props';
2
+ import { PROP_TYPE_STRING, PROP_TYPE_ARRAY, PROP_TYPE_OBJECT } from '../constants/props';
3
3
  import { get } from '../utils/get';
4
4
  import { stripTags } from '../utils/html';
5
5
  import { isPlainObject, isUndefined, isArray } from '../utils/inspect';
6
6
  import { keys } from '../utils/object';
7
- import { makeProp } from '../utils/props';
8
7
  import { warn } from '../utils/warn';
9
8
 
10
9
  // --- Constants ---
@@ -14,11 +13,31 @@ const OPTIONS_OBJECT_DEPRECATED_MSG = 'Setting prop "options" to an object is de
14
13
  // --- Props ---
15
14
 
16
15
  const props = {
17
- disabledField: makeProp(PROP_TYPE_STRING, 'disabled'),
18
- htmlField: makeProp(PROP_TYPE_STRING, 'html'),
19
- options: makeProp(PROP_TYPE_ARRAY_OBJECT, []),
20
- textField: makeProp(PROP_TYPE_STRING, 'text'),
21
- valueField: makeProp(PROP_TYPE_STRING, 'value')
16
+ disabledField: {
17
+ type: PROP_TYPE_STRING,
18
+ required: false,
19
+ default: 'disabled'
20
+ },
21
+ htmlField: {
22
+ type: PROP_TYPE_STRING,
23
+ required: false,
24
+ default: 'html'
25
+ },
26
+ options: {
27
+ type: [PROP_TYPE_ARRAY, PROP_TYPE_OBJECT],
28
+ required: false,
29
+ default: () => []
30
+ },
31
+ textField: {
32
+ type: PROP_TYPE_STRING,
33
+ required: false,
34
+ default: 'text'
35
+ },
36
+ valueField: {
37
+ type: PROP_TYPE_STRING,
38
+ required: false,
39
+ default: 'value'
40
+ }
22
41
  };
23
42
 
24
43
  // --- Mixin ---
@@ -1,11 +1,14 @@
1
1
  import { extend } from '../vue';
2
2
  import { PROP_TYPE_STRING } from '../constants/props';
3
- import { makeProp } from '../utils/props';
4
3
 
5
4
  // --- Props ---
6
5
 
7
6
  const props = {
8
- size: makeProp(PROP_TYPE_STRING)
7
+ size: {
8
+ type: PROP_TYPE_STRING,
9
+ required: false,
10
+ default: undefined
11
+ }
9
12
  };
10
13
 
11
14
  // --- Mixin ---
@@ -1,7 +1,6 @@
1
1
  import { extend } from '../vue';
2
2
  import { PROP_TYPE_BOOLEAN } from '../constants/props';
3
3
  import { isBoolean } from '../utils/inspect';
4
- import { makeProp } from '../utils/props';
5
4
  import { safeVueInstance } from '../utils/safe-vue-instance';
6
5
 
7
6
  /* Form control contextual state class computation
@@ -17,7 +16,11 @@ import { safeVueInstance } from '../utils/safe-vue-instance';
17
16
 
18
17
  const props = {
19
18
  // Tri-state prop: true, false, null (or undefined)
20
- state: makeProp(PROP_TYPE_BOOLEAN, null)
19
+ state: {
20
+ type: PROP_TYPE_BOOLEAN,
21
+ required: false,
22
+ default: null
23
+ }
21
24
  };
22
25
 
23
26
  // --- Mixin ---
@@ -1,6 +1,6 @@
1
1
  import { extend } from '../vue';
2
2
  import { EVENT_NAME_UPDATE, EVENT_NAME_INPUT, EVENT_NAME_CHANGE, EVENT_NAME_BLUR } from '../constants/events';
3
- import { PROP_TYPE_NUMBER_STRING, PROP_TYPE_BOOLEAN_STRING, PROP_TYPE_STRING, PROP_TYPE_FUNCTION, PROP_TYPE_BOOLEAN } from '../constants/props';
3
+ import { PROP_TYPE_NUMBER_STRING, PROP_TYPE_BOOLEAN, PROP_TYPE_STRING, PROP_TYPE_NUMBER, PROP_TYPE_FUNCTION } from '../constants/props';
4
4
  import { attemptFocus, attemptBlur } from '../utils/dom';
5
5
  import { stopEvent } from '../utils/events';
6
6
  import { mathMax } from '../utils/math';
@@ -8,7 +8,6 @@ import { makeModelMixin } from '../utils/model';
8
8
  import { toInteger, toFloat } from '../utils/number';
9
9
  import { sortKeys } from '../utils/object';
10
10
  import { isFunction } from '../utils/inspect';
11
- import { makeProp } from '../utils/props';
12
11
  import { toString } from '../utils/string';
13
12
 
14
13
  // --- Constants ---
@@ -28,19 +27,63 @@ const {
28
27
 
29
28
  const props = sortKeys({
30
29
  ...modelProps,
31
- ariaInvalid: makeProp(PROP_TYPE_BOOLEAN_STRING, false),
32
- autocomplete: makeProp(PROP_TYPE_STRING),
30
+ ariaInvalid: {
31
+ type: [PROP_TYPE_BOOLEAN, PROP_TYPE_STRING],
32
+ required: false,
33
+ default: false
34
+ },
35
+ autocomplete: {
36
+ type: PROP_TYPE_STRING,
37
+ required: false,
38
+ default: undefined
39
+ },
33
40
  // Debounce timeout (in ms). Not applicable with `lazy` prop
34
- debounce: makeProp(PROP_TYPE_NUMBER_STRING, 0),
35
- formatter: makeProp(PROP_TYPE_FUNCTION),
41
+ debounce: {
42
+ type: [PROP_TYPE_NUMBER, PROP_TYPE_STRING],
43
+ required: false,
44
+ default: 0
45
+ },
46
+ formatter: {
47
+ type: PROP_TYPE_FUNCTION,
48
+ required: false,
49
+ default: undefined
50
+ },
36
51
  // Only update the `v-model` on blur/change events
37
- lazy: makeProp(PROP_TYPE_BOOLEAN, false),
38
- lazyFormatter: makeProp(PROP_TYPE_BOOLEAN, false),
39
- number: makeProp(PROP_TYPE_BOOLEAN, false),
40
- placeholder: makeProp(PROP_TYPE_STRING),
41
- plaintext: makeProp(PROP_TYPE_BOOLEAN, false),
42
- readonly: makeProp(PROP_TYPE_BOOLEAN, false),
43
- trim: makeProp(PROP_TYPE_BOOLEAN, false)
52
+ lazy: {
53
+ type: PROP_TYPE_BOOLEAN,
54
+ required: false,
55
+ default: false
56
+ },
57
+ lazyFormatter: {
58
+ type: PROP_TYPE_BOOLEAN,
59
+ required: false,
60
+ default: false
61
+ },
62
+ number: {
63
+ type: PROP_TYPE_BOOLEAN,
64
+ required: false,
65
+ default: false
66
+ },
67
+ placeholder: {
68
+ type: PROP_TYPE_STRING,
69
+ required: false,
70
+ default: undefined
71
+ },
72
+ plaintext: {
73
+ type: PROP_TYPE_BOOLEAN,
74
+ required: false,
75
+ default: false
76
+ },
77
+ readonly: {
78
+ type: PROP_TYPE_BOOLEAN,
79
+ required: false,
80
+ default: false
81
+ },
82
+ trim: {
83
+ type: PROP_TYPE_BOOLEAN,
84
+ required: false,
85
+ default: false
86
+ }
44
87
  });
45
88
 
46
89
  // --- Mixin ---
@@ -1,6 +1,5 @@
1
1
  import { extend, COMPONENT_UID_KEY } from '../vue';
2
2
  import { PROP_TYPE_STRING } from '../constants/props';
3
- import { makeProp } from '../utils/props';
4
3
 
5
4
  // SSR safe client-side ID attribute generation
6
5
  // ID's can only be generated client-side, after mount
@@ -9,7 +8,11 @@ import { makeProp } from '../utils/props';
9
8
  // --- Props ---
10
9
 
11
10
  const props = {
12
- id: makeProp(PROP_TYPE_STRING)
11
+ id: {
12
+ type: PROP_TYPE_STRING,
13
+ required: false,
14
+ default: undefined
15
+ }
13
16
  };
14
17
 
15
18
  // --- Mixin ---
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gitlab/ui",
3
- "version": "130.1.0",
3
+ "version": "130.2.0",
4
4
  "description": "GitLab UI Components",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",
@@ -28,6 +28,7 @@
28
28
  "!src/vendor",
29
29
  "src/vendor/bootstrap-vue/src/**/*.{js,scss}",
30
30
  "src/vendor/bootstrap/scss/**/*.scss",
31
+ "!*.figma.{js,ts}",
31
32
  "!*.stories.js",
32
33
  "!*.snap",
33
34
  "!*.spec.{js,scss}"
@@ -38,6 +39,7 @@
38
39
  "copy-fonts": "make copy-fonts",
39
40
  "build-tokens": "make tokens",
40
41
  "sync-tokens": "node --env-file=.figma.env bin/figma_sync_tokens.mjs",
42
+ "figma:connect": "node --env-file=.figma.env node_modules/.bin/figma connect",
41
43
  "clean": "rm -r dist storybook",
42
44
  "cy:edge": "cypress run --browser edge --env grepTags=-@storybook",
43
45
  "cy:run": "cypress run --browser firefox --env grepTags=-@storybook",
@@ -99,6 +101,7 @@
99
101
  "@babel/preset-env": "^7.29.2",
100
102
  "@babel/preset-react": "^7.28.5",
101
103
  "@cypress/grep": "^4.1.1",
104
+ "@figma/code-connect": "^1.4.2",
102
105
  "@gitlab/fonts": "^1.3.1",
103
106
  "@gitlab/svgs": "*",
104
107
  "@jest/test-sequencer": "30.3.0",
@@ -132,7 +135,7 @@
132
135
  "autoprefixer": "10.4.27",
133
136
  "axe-playwright": "^2.2.2",
134
137
  "babel-loader": "^9.2.1",
135
- "cypress": "15.12.0",
138
+ "cypress": "15.13.0",
136
139
  "cypress-real-events": "^1.15.0",
137
140
  "dompurify": "^3.1.2",
138
141
  "emoji-regex": "^10.6.0",
@@ -354,8 +354,7 @@ export default {
354
354
  },
355
355
  },
356
356
  mounted() {
357
- // eslint-disable-next-line @gitlab/vue-prefer-dollar-scopedslots
358
- if (!this.$slots.default && !this.$attrs['aria-label'] && !this.$props.label) {
357
+ if (!('default' in this.$scopedSlots) && !this.$attrs['aria-label'] && !this.label) {
359
358
  logWarning('Accessible name missing. Please add inner text or aria-label.', {
360
359
  name: 'GlButton',
361
360
  element: this.$el,
@@ -195,6 +195,14 @@ export default {
195
195
  required: false,
196
196
  default: null,
197
197
  },
198
+ /**
199
+ * The `aria-label` attribute value for the toggle `button`.
200
+ */
201
+ ariaLabel: {
202
+ type: String,
203
+ required: false,
204
+ default: null,
205
+ },
198
206
  /**
199
207
  * Custom value to be passed to the offset middleware.
200
208
  * https://floating-ui.com/docs/offset
@@ -302,6 +310,7 @@ export default {
302
310
  'aria-expanded': String(this.visible),
303
311
  'aria-haspopup': this.ariaHaspopup,
304
312
  'aria-labelledby': this.toggleLabelledBy,
313
+ 'aria-label': this.ariaLabel || undefined,
305
314
  'aria-activedescendant': this.ariaActiveDescendant,
306
315
  };
307
316
  },
@@ -1,6 +1,6 @@
1
1
  <script>
2
2
  import { clamp, uniqueId } from 'lodash-es';
3
- import { stopEvent, filterVisible } from '../../../../utils/utils';
3
+ import { stopEvent, filterVisible, logWarning } from '../../../../utils/utils';
4
4
  import {
5
5
  GL_DROPDOWN_SHOWN,
6
6
  GL_DROPDOWN_HIDDEN,
@@ -163,6 +163,17 @@ export default {
163
163
  required: false,
164
164
  default: null,
165
165
  },
166
+ /**
167
+ * The `aria-label` attribute value for the toggle button.
168
+ * Use when there is no visible label element to reference with `toggleAriaLabelledBy`.
169
+ * Do not provide both `toggleAriaLabel` and `toggleAriaLabelledBy`.
170
+ * When both are present, `toggleAriaLabelledBy` takes precedence per the WAI-ARIA spec.
171
+ */
172
+ toggleAriaLabel: {
173
+ type: String,
174
+ required: false,
175
+ default: null,
176
+ },
166
177
  /**
167
178
  * The `aria-labelledby` attribute value for the list of options
168
179
  * Provide the string of ids seperated by space
@@ -251,6 +262,16 @@ export default {
251
262
  },
252
263
  },
253
264
  mounted() {
265
+ if (this.toggleAriaLabel && this.toggleAriaLabelledBy) {
266
+ logWarning(
267
+ 'Do not provide both `toggleAriaLabel` and `toggleAriaLabelledBy`. ' +
268
+ 'When both are present, `toggleAriaLabelledBy` takes precedence and `toggleAriaLabel` is ignored. ' +
269
+ 'See https://design.gitlab.com/components/dropdown-disclosure/#accessibility',
270
+ {
271
+ name: 'GlDisclosureDropdown',
272
+ },
273
+ );
274
+ }
254
275
  if (this.startOpened) {
255
276
  this.open();
256
277
  }
@@ -374,6 +395,7 @@ export default {
374
395
  <gl-base-dropdown
375
396
  ref="baseDropdown"
376
397
  :aria-labelledby="toggleAriaLabelledBy"
398
+ :aria-label="toggleAriaLabelledBy ? undefined : toggleAriaLabel"
377
399
  :arrow-element="$refs.disclosureArrow"
378
400
  :toggle-id="toggleId"
379
401
  :toggle-text="toggleText"
@@ -20,7 +20,7 @@ import {
20
20
  } from '../constants/popper'
21
21
  import {
22
22
  PROP_TYPE_BOOLEAN,
23
- PROP_TYPE_NUMBER_STRING,
23
+ PROP_TYPE_NUMBER,
24
24
  PROP_TYPE_OBJECT,
25
25
  PROP_TYPE_STRING
26
26
  } from '../constants/props'
@@ -29,7 +29,6 @@ import { BvEvent } from '../utils/bv-event.class'
29
29
  import { attemptFocus, closest, contains, isVisible, requestAF, selectAll } from '../utils/dom'
30
30
  import { getRootEventName, stopEvent } from '../utils/events'
31
31
  import { mergeDeep, sortKeys } from '../utils/object'
32
- import { makeProp } from '../utils/props'
33
32
  import { warn } from '../utils/warn'
34
33
  import { clickOutMixin } from './click-out'
35
34
  import { focusInMixin } from './focus-in'
@@ -62,22 +61,58 @@ export const props = sortKeys({
62
61
  ...idProps,
63
62
  // String: `scrollParent`, `window` or `viewport`
64
63
  // HTMLElement: HTML Element reference
65
- boundary: makeProp([HTMLElement, PROP_TYPE_STRING], 'scrollParent'),
66
- disabled: makeProp(PROP_TYPE_BOOLEAN, false),
64
+ boundary: {
65
+ type: [HTMLElement, PROP_TYPE_STRING],
66
+ required: false,
67
+ default: 'scrollParent'
68
+ },
69
+ disabled: {
70
+ type: PROP_TYPE_BOOLEAN,
71
+ required: false,
72
+ default: false
73
+ },
67
74
  // Place left if possible
68
- dropleft: makeProp(PROP_TYPE_BOOLEAN, false),
75
+ dropleft: {
76
+ type: PROP_TYPE_BOOLEAN,
77
+ required: false,
78
+ default: false
79
+ },
69
80
  // Place right if possible
70
- dropright: makeProp(PROP_TYPE_BOOLEAN, false),
81
+ dropright: {
82
+ type: PROP_TYPE_BOOLEAN,
83
+ required: false,
84
+ default: false
85
+ },
71
86
  // Place on top if possible
72
- dropup: makeProp(PROP_TYPE_BOOLEAN, false),
87
+ dropup: {
88
+ type: PROP_TYPE_BOOLEAN,
89
+ required: false,
90
+ default: false
91
+ },
73
92
  // Disable auto-flipping of menu from bottom <=> top
74
- noFlip: makeProp(PROP_TYPE_BOOLEAN, false),
93
+ noFlip: {
94
+ type: PROP_TYPE_BOOLEAN,
95
+ required: false,
96
+ default: false
97
+ },
75
98
  // Number of pixels or a CSS unit value to offset menu
76
99
  // (i.e. `1px`, `1rem`, etc.)
77
- offset: makeProp(PROP_TYPE_NUMBER_STRING, 0),
78
- popperOpts: makeProp(PROP_TYPE_OBJECT, {}),
100
+ offset: {
101
+ type: [PROP_TYPE_NUMBER, PROP_TYPE_STRING],
102
+ required: false,
103
+ default: 0
104
+ },
105
+ popperOpts: {
106
+ type: PROP_TYPE_OBJECT,
107
+ required: false,
108
+ default: () => ({})
109
+ },
79
110
  // Right align menu (default is left align)
80
- right: makeProp(PROP_TYPE_BOOLEAN, false)
111
+ right: {
112
+ type: PROP_TYPE_BOOLEAN,
113
+ required: false,
114
+ default: false
115
+ }
81
116
  })
82
117
 
83
118
  // --- Mixin ---
@@ -1,7 +1,6 @@
1
1
  import { extend } from '../vue'
2
2
  import { PROP_TYPE_BOOLEAN, PROP_TYPE_STRING } from '../constants/props'
3
3
  import { attemptFocus, isVisible, matches, requestAF, select } from '../utils/dom'
4
- import { makeProp } from '../utils/props'
5
4
 
6
5
  // --- Constants ---
7
6
 
@@ -10,12 +9,36 @@ const SELECTOR = 'input, textarea, select'
10
9
  // --- Props ---
11
10
 
12
11
  export const props = {
13
- autofocus: makeProp(PROP_TYPE_BOOLEAN, false),
14
- disabled: makeProp(PROP_TYPE_BOOLEAN, false),
15
- form: makeProp(PROP_TYPE_STRING),
16
- id: makeProp(PROP_TYPE_STRING),
17
- name: makeProp(PROP_TYPE_STRING),
18
- required: makeProp(PROP_TYPE_BOOLEAN, false)
12
+ autofocus: {
13
+ type: PROP_TYPE_BOOLEAN,
14
+ required: false,
15
+ default: false
16
+ },
17
+ disabled: {
18
+ type: PROP_TYPE_BOOLEAN,
19
+ required: false,
20
+ default: false
21
+ },
22
+ form: {
23
+ type: PROP_TYPE_STRING,
24
+ required: false,
25
+ default: undefined
26
+ },
27
+ id: {
28
+ type: PROP_TYPE_STRING,
29
+ required: false,
30
+ default: undefined
31
+ },
32
+ name: {
33
+ type: PROP_TYPE_STRING,
34
+ required: false,
35
+ default: undefined
36
+ },
37
+ required: {
38
+ type: PROP_TYPE_BOOLEAN,
39
+ required: false,
40
+ default: false
41
+ }
19
42
  }
20
43
 
21
44
  // --- Mixin ---
@@ -1,11 +1,14 @@
1
1
  import { extend } from '../vue'
2
2
  import { PROP_TYPE_BOOLEAN } from '../constants/props'
3
- import { makeProp } from '../utils/props'
4
3
 
5
4
  // --- Props ---
6
5
 
7
6
  export const props = {
8
- plain: makeProp(PROP_TYPE_BOOLEAN, false)
7
+ plain: {
8
+ type: PROP_TYPE_BOOLEAN,
9
+ required: false,
10
+ default: false
11
+ }
9
12
  }
10
13
 
11
14
  // --- Mixin ---
@@ -1,10 +1,9 @@
1
1
  import { extend } from '../vue'
2
- import { PROP_TYPE_ARRAY_OBJECT, PROP_TYPE_STRING } from '../constants/props'
2
+ import { PROP_TYPE_ARRAY, PROP_TYPE_OBJECT, PROP_TYPE_STRING } from '../constants/props'
3
3
  import { get } from '../utils/get'
4
4
  import { stripTags } from '../utils/html'
5
5
  import { isArray, isPlainObject, isUndefined } from '../utils/inspect'
6
6
  import { keys } from '../utils/object'
7
- import { makeProp } from '../utils/props'
8
7
  import { warn } from '../utils/warn'
9
8
 
10
9
  // --- Constants ---
@@ -15,11 +14,31 @@ const OPTIONS_OBJECT_DEPRECATED_MSG =
15
14
  // --- Props ---
16
15
 
17
16
  export const props = {
18
- disabledField: makeProp(PROP_TYPE_STRING, 'disabled'),
19
- htmlField: makeProp(PROP_TYPE_STRING, 'html'),
20
- options: makeProp(PROP_TYPE_ARRAY_OBJECT, []),
21
- textField: makeProp(PROP_TYPE_STRING, 'text'),
22
- valueField: makeProp(PROP_TYPE_STRING, 'value')
17
+ disabledField: {
18
+ type: PROP_TYPE_STRING,
19
+ required: false,
20
+ default: 'disabled'
21
+ },
22
+ htmlField: {
23
+ type: PROP_TYPE_STRING,
24
+ required: false,
25
+ default: 'html'
26
+ },
27
+ options: {
28
+ type: [PROP_TYPE_ARRAY, PROP_TYPE_OBJECT],
29
+ required: false,
30
+ default: () => []
31
+ },
32
+ textField: {
33
+ type: PROP_TYPE_STRING,
34
+ required: false,
35
+ default: 'text'
36
+ },
37
+ valueField: {
38
+ type: PROP_TYPE_STRING,
39
+ required: false,
40
+ default: 'value'
41
+ }
23
42
  }
24
43
 
25
44
  // --- Mixin ---
@@ -1,11 +1,14 @@
1
1
  import { extend } from '../vue'
2
2
  import { PROP_TYPE_STRING } from '../constants/props'
3
- import { makeProp } from '../utils/props'
4
3
 
5
4
  // --- Props ---
6
5
 
7
6
  export const props = {
8
- size: makeProp(PROP_TYPE_STRING)
7
+ size: {
8
+ type: PROP_TYPE_STRING,
9
+ required: false,
10
+ default: undefined
11
+ }
9
12
  }
10
13
 
11
14
  // --- Mixin ---
@@ -9,14 +9,17 @@
9
9
  import { extend } from '../vue'
10
10
  import { PROP_TYPE_BOOLEAN } from '../constants/props'
11
11
  import { isBoolean } from '../utils/inspect'
12
- import { makeProp } from '../utils/props'
13
12
  import { safeVueInstance } from '../utils/safe-vue-instance'
14
13
 
15
14
  // --- Props ---
16
15
 
17
16
  export const props = {
18
17
  // Tri-state prop: true, false, null (or undefined)
19
- state: makeProp(PROP_TYPE_BOOLEAN, null)
18
+ state: {
19
+ type: PROP_TYPE_BOOLEAN,
20
+ required: false,
21
+ default: null
22
+ }
20
23
  }
21
24
 
22
25
  // --- Mixin ---
@@ -7,8 +7,8 @@ import {
7
7
  } from '../constants/events'
8
8
  import {
9
9
  PROP_TYPE_BOOLEAN,
10
- PROP_TYPE_BOOLEAN_STRING,
11
10
  PROP_TYPE_FUNCTION,
11
+ PROP_TYPE_NUMBER,
12
12
  PROP_TYPE_NUMBER_STRING,
13
13
  PROP_TYPE_STRING
14
14
  } from '../constants/props'
@@ -19,7 +19,6 @@ import { makeModelMixin } from '../utils/model'
19
19
  import { toInteger, toFloat } from '../utils/number'
20
20
  import { sortKeys } from '../utils/object'
21
21
  import { isFunction } from '../utils/inspect'
22
- import { makeProp } from '../utils/props'
23
22
  import { toString } from '../utils/string'
24
23
 
25
24
  // --- Constants ---
@@ -41,19 +40,63 @@ export { MODEL_PROP_NAME, MODEL_EVENT_NAME }
41
40
 
42
41
  export const props = sortKeys({
43
42
  ...modelProps,
44
- ariaInvalid: makeProp(PROP_TYPE_BOOLEAN_STRING, false),
45
- autocomplete: makeProp(PROP_TYPE_STRING),
43
+ ariaInvalid: {
44
+ type: [PROP_TYPE_BOOLEAN, PROP_TYPE_STRING],
45
+ required: false,
46
+ default: false
47
+ },
48
+ autocomplete: {
49
+ type: PROP_TYPE_STRING,
50
+ required: false,
51
+ default: undefined
52
+ },
46
53
  // Debounce timeout (in ms). Not applicable with `lazy` prop
47
- debounce: makeProp(PROP_TYPE_NUMBER_STRING, 0),
48
- formatter: makeProp(PROP_TYPE_FUNCTION),
54
+ debounce: {
55
+ type: [PROP_TYPE_NUMBER, PROP_TYPE_STRING],
56
+ required: false,
57
+ default: 0
58
+ },
59
+ formatter: {
60
+ type: PROP_TYPE_FUNCTION,
61
+ required: false,
62
+ default: undefined
63
+ },
49
64
  // Only update the `v-model` on blur/change events
50
- lazy: makeProp(PROP_TYPE_BOOLEAN, false),
51
- lazyFormatter: makeProp(PROP_TYPE_BOOLEAN, false),
52
- number: makeProp(PROP_TYPE_BOOLEAN, false),
53
- placeholder: makeProp(PROP_TYPE_STRING),
54
- plaintext: makeProp(PROP_TYPE_BOOLEAN, false),
55
- readonly: makeProp(PROP_TYPE_BOOLEAN, false),
56
- trim: makeProp(PROP_TYPE_BOOLEAN, false)
65
+ lazy: {
66
+ type: PROP_TYPE_BOOLEAN,
67
+ required: false,
68
+ default: false
69
+ },
70
+ lazyFormatter: {
71
+ type: PROP_TYPE_BOOLEAN,
72
+ required: false,
73
+ default: false
74
+ },
75
+ number: {
76
+ type: PROP_TYPE_BOOLEAN,
77
+ required: false,
78
+ default: false
79
+ },
80
+ placeholder: {
81
+ type: PROP_TYPE_STRING,
82
+ required: false,
83
+ default: undefined
84
+ },
85
+ plaintext: {
86
+ type: PROP_TYPE_BOOLEAN,
87
+ required: false,
88
+ default: false
89
+ },
90
+ readonly: {
91
+ type: PROP_TYPE_BOOLEAN,
92
+ required: false,
93
+ default: false
94
+ },
95
+ trim: {
96
+ type: PROP_TYPE_BOOLEAN,
97
+ required: false,
98
+ default: false
99
+ }
57
100
  })
58
101
 
59
102
  // --- Mixin ---
@@ -3,12 +3,15 @@
3
3
  // `this._uid` is not synched between server and client
4
4
  import { COMPONENT_UID_KEY, extend } from '../vue'
5
5
  import { PROP_TYPE_STRING } from '../constants/props'
6
- import { makeProp } from '../utils/props'
7
6
 
8
7
  // --- Props ---
9
8
 
10
9
  export const props = {
11
- id: makeProp(PROP_TYPE_STRING)
10
+ id: {
11
+ type: PROP_TYPE_STRING,
12
+ required: false,
13
+ default: undefined
14
+ }
12
15
  }
13
16
 
14
17
  // --- Mixin ---