@gitlab/ui 109.2.0 → 109.2.1

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,10 @@
1
+ ## [109.2.1](https://gitlab.com/gitlab-org/gitlab-ui/compare/v109.2.0...v109.2.1) (2025-03-07)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * **combobox:** Combobox ARIA labeling ([2d46733](https://gitlab.com/gitlab-org/gitlab-ui/commit/2d4673351a44c8413188dbe708a06ea973694a32))
7
+
1
8
  # [109.2.0](https://gitlab.com/gitlab-org/gitlab-ui/compare/v109.1.0...v109.2.0) (2025-03-05)
2
9
 
3
10
 
@@ -59,6 +59,11 @@ var script = {
59
59
  type: String,
60
60
  required: false,
61
61
  default: ''
62
+ },
63
+ role: {
64
+ type: String,
65
+ required: false,
66
+ default: null
62
67
  }
63
68
  },
64
69
  computed: {
@@ -70,6 +75,13 @@ var script = {
70
75
  // Support 'href' and Vue Router's 'to'
71
76
  return href || to ? BDropdownItem : BDropdownItemButton;
72
77
  },
78
+ bootstrapComponentProps() {
79
+ const props = {
80
+ ...this.$attrs
81
+ };
82
+ if (this.role) props.role = this.role;
83
+ return props;
84
+ },
73
85
  iconColorCss() {
74
86
  return variantCssColorMap[this.iconColor] || 'gl-fill-icon-default';
75
87
  },
@@ -94,7 +106,7 @@ var script = {
94
106
  const __vue_script__ = script;
95
107
 
96
108
  /* template */
97
- var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c(_vm.bootstrapComponent,_vm._g(_vm._b({tag:"component",staticClass:"gl-dropdown-item"},'component',_vm.$attrs,false),_vm.$listeners),[(_vm.shouldShowCheckIcon)?_c('gl-icon',{class:['gl-dropdown-item-check-icon', { 'gl-invisible': !_vm.isChecked }, _vm.checkedClasses],attrs:{"name":"mobile-issue-close","data-testid":"dropdown-item-checkbox"}}):_vm._e(),_vm._v(" "),(_vm.iconName)?_c('gl-icon',{class:['gl-dropdown-item-icon', _vm.iconColorCss],attrs:{"name":_vm.iconName}}):_vm._e(),_vm._v(" "),(_vm.avatarUrl)?_c('gl-avatar',{attrs:{"size":32,"src":_vm.avatarUrl}}):_vm._e(),_vm._v(" "),_c('div',{staticClass:"gl-dropdown-item-text-wrapper"},[_c('p',{staticClass:"gl-dropdown-item-text-primary"},[_vm._t("default")],2),_vm._v(" "),(_vm.secondaryText)?_c('p',{staticClass:"gl-dropdown-item-text-secondary"},[_vm._v(_vm._s(_vm.secondaryText))]):_vm._e()]),_vm._v(" "),(_vm.iconRightName)?_c('gl-button',{attrs:{"size":"small","icon":_vm.iconRightName,"aria-label":_vm.iconRightAriaLabel || _vm.iconRightName},on:{"click":function($event){$event.stopPropagation();$event.preventDefault();return _vm.handleClickIconRight.apply(null, arguments)}}}):_vm._e()],1)};
109
+ var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c(_vm.bootstrapComponent,_vm._g(_vm._b({tag:"component",staticClass:"gl-dropdown-item"},'component',_vm.bootstrapComponentProps,false),_vm.$listeners),[(_vm.shouldShowCheckIcon)?_c('gl-icon',{class:['gl-dropdown-item-check-icon', { 'gl-invisible': !_vm.isChecked }, _vm.checkedClasses],attrs:{"name":"mobile-issue-close","data-testid":"dropdown-item-checkbox"}}):_vm._e(),_vm._v(" "),(_vm.iconName)?_c('gl-icon',{class:['gl-dropdown-item-icon', _vm.iconColorCss],attrs:{"name":_vm.iconName}}):_vm._e(),_vm._v(" "),(_vm.avatarUrl)?_c('gl-avatar',{attrs:{"size":32,"src":_vm.avatarUrl}}):_vm._e(),_vm._v(" "),_c('div',{staticClass:"gl-dropdown-item-text-wrapper"},[_c('p',{staticClass:"gl-dropdown-item-text-primary"},[_vm._t("default")],2),_vm._v(" "),(_vm.secondaryText)?_c('p',{staticClass:"gl-dropdown-item-text-secondary"},[_vm._v(_vm._s(_vm.secondaryText))]):_vm._e()]),_vm._v(" "),(_vm.iconRightName)?_c('gl-button',{attrs:{"size":"small","icon":_vm.iconRightName,"aria-label":_vm.iconRightAriaLabel || _vm.iconRightName},on:{"click":function($event){$event.stopPropagation();$event.preventDefault();return _vm.handleClickIconRight.apply(null, arguments)}}}):_vm._e()],1)};
98
110
  var __vue_staticRenderFns__ = [];
99
111
 
100
112
  /* style */
@@ -68,12 +68,13 @@ var script = {
68
68
  arrowCounter: -1,
69
69
  userDismissedResults: false,
70
70
  suggestionsId: uniqueId('token-suggestions-'),
71
- inputId: uniqueId('token-input-')
71
+ inputId: uniqueId('token-input-'),
72
+ dropdownItemComponent: GlDropdownItem
72
73
  };
73
74
  },
74
75
  computed: {
75
- ariaExpanded() {
76
- return this.showSuggestions.toString();
76
+ isExpanded() {
77
+ return this.showSuggestions && !this.userDismissedResults;
77
78
  },
78
79
  showAutocomplete() {
79
80
  return this.showSuggestions ? 'off' : 'on';
@@ -140,6 +141,14 @@ var script = {
140
141
  this.arrowCounter = newCount;
141
142
  this.focusItem(newCount);
142
143
  },
144
+ onArrowLeft() {
145
+ // don't prevent default, we want the cursor to move
146
+ this.$refs.input.focus();
147
+ },
148
+ onArrowRight() {
149
+ // don't prevent default, we want the cursor to move
150
+ this.$refs.input.focus();
151
+ },
143
152
  onEsc() {
144
153
  if (!this.showSuggestions) {
145
154
  this.$emit('input', '');
@@ -195,7 +204,7 @@ var script = {
195
204
  const __vue_script__ = script;
196
205
 
197
206
  /* template */
198
- var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:"gl-form-combobox dropdown",attrs:{"role":"combobox","aria-owns":_vm.suggestionsId,"aria-expanded":_vm.ariaExpanded}},[_c('gl-form-group',{attrs:{"label":_vm.labelText,"label-for":_vm.inputId,"label-sr-only":_vm.labelSrOnly}},[_c('gl-form-input',{attrs:{"id":_vm.inputId,"value":_vm.displayedValue,"type":"text","role":"searchbox","autocomplete":_vm.showAutocomplete,"aria-autocomplete":"list","aria-controls":_vm.suggestionsId,"aria-haspopup":"listbox","autofocus":_vm.autofocus,"placeholder":_vm.placeholder},on:{"input":_vm.onEntry,"focus":_vm.resetCounter,"keydown":[function($event){if(!$event.type.indexOf('key')&&_vm._k($event.keyCode,"down",40,$event.key,["Down","ArrowDown"])){ return null; }return _vm.onArrowDown.apply(null, arguments)},function($event){if(!$event.type.indexOf('key')&&_vm._k($event.keyCode,"up",38,$event.key,["Up","ArrowUp"])){ return null; }return _vm.onArrowUp.apply(null, arguments)},function($event){if(!$event.type.indexOf('key')&&_vm._k($event.keyCode,"esc",27,$event.key,["Esc","Escape"])){ return null; }$event.stopPropagation();return _vm.onEsc.apply(null, arguments)},function($event){if(!$event.type.indexOf('key')&&_vm._k($event.keyCode,"tab",9,$event.key,"Tab")){ return null; }return _vm.closeSuggestions.apply(null, arguments)}]}})],1),_vm._v(" "),_c('ul',{directives:[{name:"show",rawName:"v-show",value:(_vm.showSuggestions && !_vm.userDismissedResults),expression:"showSuggestions && !userDismissedResults"}],ref:"suggestionsMenu",staticClass:"dropdown-menu gl-form-combobox-inner gl-mb-0 gl-flex gl-w-full gl-list-none gl-flex-col gl-border-dropdown gl-bg-dropdown gl-pl-0",attrs:{"id":_vm.suggestionsId,"data-testid":"combobox-dropdown"},on:{"keydown":[function($event){if(!$event.type.indexOf('key')&&_vm._k($event.keyCode,"down",40,$event.key,["Down","ArrowDown"])){ return null; }return _vm.onArrowDown.apply(null, arguments)},function($event){if(!$event.type.indexOf('key')&&_vm._k($event.keyCode,"up",38,$event.key,["Up","ArrowUp"])){ return null; }return _vm.onArrowUp.apply(null, arguments)},function($event){if(!$event.type.indexOf('key')&&_vm._k($event.keyCode,"esc",27,$event.key,["Esc","Escape"])){ return null; }$event.stopPropagation();return _vm.onEsc.apply(null, arguments)}]}},[_c('li',{staticClass:"show-dropdown gl-overflow-y-auto"},[_c('ul',{staticClass:"gl-mb-0 gl-list-none gl-pl-0"},_vm._l((_vm.results),function(result,i){return _c('gl-dropdown-item',{key:i,ref:"results",refInFor:true,attrs:{"role":"option","aria-selected":i === _vm.arrowCounter,"tabindex":"-1"},on:{"click":function($event){return _vm.selectToken(result)}},nativeOn:{"keydown":function($event){if(!$event.type.indexOf('key')&&_vm._k($event.keyCode,"enter",13,$event.key,"Enter")){ return null; }return _vm.selectToken(result)}}},[_vm._t("result",function(){return [_vm._v(_vm._s(result))]},{"item":result})],2)}),1)]),_vm._v(" "),(_vm.resultsLength > 0 && _vm.actionList.length > 0)?_c('gl-dropdown-divider'):_vm._e(),_vm._v(" "),_c('li',[_c('ul',{staticClass:"gl-mb-0 gl-list-none gl-pl-0"},_vm._l((_vm.actionList),function(action,i){return _c('gl-dropdown-item',{key:i + _vm.resultsLength,attrs:{"role":"option","aria-selected":i + _vm.resultsLength === _vm.arrowCounter,"tabindex":"-1","data-testid":"combobox-action"},on:{"click":function($event){return _vm.selectAction(action)}},nativeOn:{"keydown":function($event){if(!$event.type.indexOf('key')&&_vm._k($event.keyCode,"enter",13,$event.key,"Enter")){ return null; }return _vm.selectAction(action)}}},[_vm._t("action",function(){return [_vm._v(_vm._s(action.label))]},{"item":action})],2)}),1)])],1)],1)};
207
+ var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:"gl-form-combobox dropdown"},[_c('gl-form-group',{attrs:{"label":_vm.labelText,"label-for":_vm.inputId,"label-sr-only":_vm.labelSrOnly}},[_c('gl-form-input',{ref:"input",attrs:{"id":_vm.inputId,"value":_vm.displayedValue,"type":"text","role":"combobox","aria-expanded":String(_vm.isExpanded),"aria-controls":_vm.suggestionsId,"aria-owns":_vm.isExpanded ? _vm.suggestionsId : null,"aria-autocomplete":"list","aria-haspopup":"listbox","aria-activedescendant":_vm.arrowCounter >= 0 ? (_vm.suggestionsId + "-option-" + _vm.arrowCounter) : undefined,"autofocus":_vm.autofocus,"placeholder":_vm.placeholder},on:{"input":_vm.onEntry,"focus":_vm.resetCounter,"keydown":[function($event){if(!$event.type.indexOf('key')&&_vm._k($event.keyCode,"down",40,$event.key,["Down","ArrowDown"])){ return null; }return _vm.onArrowDown.apply(null, arguments)},function($event){if(!$event.type.indexOf('key')&&_vm._k($event.keyCode,"up",38,$event.key,["Up","ArrowUp"])){ return null; }return _vm.onArrowUp.apply(null, arguments)},function($event){if(!$event.type.indexOf('key')&&_vm._k($event.keyCode,"left",37,$event.key,["Left","ArrowLeft"])){ return null; }if('button' in $event && $event.button !== 0){ return null; }return _vm.onArrowLeft.apply(null, arguments)},function($event){if(!$event.type.indexOf('key')&&_vm._k($event.keyCode,"right",39,$event.key,["Right","ArrowRight"])){ return null; }if('button' in $event && $event.button !== 2){ return null; }return _vm.onArrowRight.apply(null, arguments)},function($event){if(!$event.type.indexOf('key')&&_vm._k($event.keyCode,"esc",27,$event.key,["Esc","Escape"])){ return null; }$event.stopPropagation();return _vm.onEsc.apply(null, arguments)},function($event){if(!$event.type.indexOf('key')&&_vm._k($event.keyCode,"tab",9,$event.key,"Tab")){ return null; }return _vm.closeSuggestions.apply(null, arguments)}]}})],1),_vm._v(" "),_c('div',{directives:[{name:"show",rawName:"v-show",value:(_vm.isExpanded),expression:"isExpanded"}],ref:"suggestionsMenu",staticClass:"dropdown-menu gl-form-combobox-inner gl-mb-0 gl-flex gl-w-full gl-list-none gl-flex-col gl-border-dropdown gl-bg-dropdown gl-pl-0",attrs:{"id":_vm.suggestionsId,"data-testid":"combobox-dropdown","role":"listbox"},on:{"keydown":[function($event){if(!$event.type.indexOf('key')&&_vm._k($event.keyCode,"down",40,$event.key,["Down","ArrowDown"])){ return null; }return _vm.onArrowDown.apply(null, arguments)},function($event){if(!$event.type.indexOf('key')&&_vm._k($event.keyCode,"up",38,$event.key,["Up","ArrowUp"])){ return null; }return _vm.onArrowUp.apply(null, arguments)},function($event){if(!$event.type.indexOf('key')&&_vm._k($event.keyCode,"left",37,$event.key,["Left","ArrowLeft"])){ return null; }if('button' in $event && $event.button !== 0){ return null; }return _vm.onArrowLeft.apply(null, arguments)},function($event){if(!$event.type.indexOf('key')&&_vm._k($event.keyCode,"right",39,$event.key,["Right","ArrowRight"])){ return null; }if('button' in $event && $event.button !== 2){ return null; }return _vm.onArrowRight.apply(null, arguments)},function($event){if(!$event.type.indexOf('key')&&_vm._k($event.keyCode,"esc",27,$event.key,["Esc","Escape"])){ return null; }$event.stopPropagation();return _vm.onEsc.apply(null, arguments)}]}},[_c('div',{staticClass:"gl-overflow-y-auto"},_vm._l((_vm.results),function(result,i){return _c('gl-dropdown-item',{key:i,ref:"results",refInFor:true,attrs:{"id":(_vm.suggestionsId + "-option-" + i),"active":i === _vm.arrowCounter,"tabindex":"-1","role":"option","data-testid":"combobox-result"},on:{"click":function($event){return _vm.selectToken(result)}},nativeOn:{"keydown":function($event){if(!$event.type.indexOf('key')&&_vm._k($event.keyCode,"enter",13,$event.key,"Enter")){ return null; }return _vm.selectToken(result)}}},[_vm._t("result",function(){return [_vm._v(_vm._s(result))]},{"item":result})],2)}),1),_vm._v(" "),(_vm.resultsLength > 0 && _vm.actionList.length > 0)?_c('gl-dropdown-divider',{attrs:{"aria-hidden":"true"}}):_vm._e(),_vm._v(" "),_c('div',_vm._l((_vm.actionList),function(action,i){return _c('gl-dropdown-item',{key:i + _vm.resultsLength,attrs:{"id":(_vm.suggestionsId + "-option-" + (i + _vm.resultsLength)),"active":i + _vm.resultsLength === _vm.arrowCounter,"tabindex":"-1","role":"option","data-testid":"combobox-action"},on:{"click":function($event){return _vm.selectAction(action)},"keydown":[function($event){if(!$event.type.indexOf('key')&&_vm._k($event.keyCode,"left",37,$event.key,["Left","ArrowLeft"])){ return null; }if('button' in $event && $event.button !== 0){ return null; }return _vm.onArrowLeft.apply(null, arguments)},function($event){if(!$event.type.indexOf('key')&&_vm._k($event.keyCode,"right",39,$event.key,["Right","ArrowRight"])){ return null; }if('button' in $event && $event.button !== 2){ return null; }return _vm.onArrowRight.apply(null, arguments)}]},nativeOn:{"keydown":function($event){if(!$event.type.indexOf('key')&&_vm._k($event.keyCode,"enter",13,$event.key,"Enter")){ return null; }return _vm.selectAction(action)}}},[_vm._t("action",function(){return [_vm._v(_vm._s(action.label))]},{"item":action})],2)}),1)],1)],1)};
199
208
  var __vue_staticRenderFns__ = [];
200
209
 
201
210
  /* style */
@@ -13,7 +13,8 @@ const props = makePropsConfigurable({
13
13
  activeClass: makeProp(PROP_TYPE_STRING, 'active'),
14
14
  buttonClass: makeProp(PROP_TYPE_ARRAY_OBJECT_STRING),
15
15
  disabled: makeProp(PROP_TYPE_BOOLEAN, false),
16
- variant: makeProp(PROP_TYPE_STRING)
16
+ variant: makeProp(PROP_TYPE_STRING),
17
+ role: makeProp(PROP_TYPE_STRING, 'menuitem')
17
18
  }, NAME_DROPDOWN_ITEM_BUTTON);
18
19
 
19
20
  // --- Main component ---
@@ -36,9 +37,10 @@ const BDropdownItemButton = /*#__PURE__*/extend({
36
37
  computedAttrs() {
37
38
  return {
38
39
  ...this.bvAttrs,
39
- role: 'menuitem',
40
+ role: this.role,
40
41
  type: 'button',
41
- disabled: this.disabled
42
+ disabled: this.disabled,
43
+ 'aria-selected': this.active ? 'true' : null
42
44
  };
43
45
  }
44
46
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gitlab/ui",
3
- "version": "109.2.0",
3
+ "version": "109.2.1",
4
4
  "description": "GitLab UI Components",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",
@@ -60,6 +60,11 @@ export default {
60
60
  required: false,
61
61
  default: '',
62
62
  },
63
+ role: {
64
+ type: String,
65
+ required: false,
66
+ default: null,
67
+ },
63
68
  },
64
69
  computed: {
65
70
  bootstrapComponent() {
@@ -67,6 +72,11 @@ export default {
67
72
  // Support 'href' and Vue Router's 'to'
68
73
  return href || to ? BDropdownItem : BDropdownItemButton;
69
74
  },
75
+ bootstrapComponentProps() {
76
+ const props = { ...this.$attrs };
77
+ if (this.role) props.role = this.role;
78
+ return props;
79
+ },
70
80
  iconColorCss() {
71
81
  return variantCssColorMap[this.iconColor] || 'gl-fill-icon-default';
72
82
  },
@@ -90,7 +100,12 @@ export default {
90
100
  </script>
91
101
 
92
102
  <template>
93
- <component :is="bootstrapComponent" class="gl-dropdown-item" v-bind="$attrs" v-on="$listeners">
103
+ <component
104
+ :is="bootstrapComponent"
105
+ class="gl-dropdown-item"
106
+ v-bind="bootstrapComponentProps"
107
+ v-on="$listeners"
108
+ >
94
109
  <gl-icon
95
110
  v-if="shouldShowCheckIcon"
96
111
  name="mobile-issue-close"
@@ -70,11 +70,12 @@ export default {
70
70
  userDismissedResults: false,
71
71
  suggestionsId: uniqueId('token-suggestions-'),
72
72
  inputId: uniqueId('token-input-'),
73
+ dropdownItemComponent: GlDropdownItem,
73
74
  };
74
75
  },
75
76
  computed: {
76
- ariaExpanded() {
77
- return this.showSuggestions.toString();
77
+ isExpanded() {
78
+ return this.showSuggestions && !this.userDismissedResults;
78
79
  },
79
80
  showAutocomplete() {
80
81
  return this.showSuggestions ? 'off' : 'on';
@@ -149,6 +150,14 @@ export default {
149
150
  this.arrowCounter = newCount;
150
151
  this.focusItem(newCount);
151
152
  },
153
+ onArrowLeft() {
154
+ // don't prevent default, we want the cursor to move
155
+ this.$refs.input.focus();
156
+ },
157
+ onArrowRight() {
158
+ // don't prevent default, we want the cursor to move
159
+ this.$refs.input.focus();
160
+ },
152
161
  onEsc() {
153
162
  if (!this.showSuggestions) {
154
163
  this.$emit('input', '');
@@ -202,79 +211,88 @@ export default {
202
211
  },
203
212
  };
204
213
  </script>
214
+
205
215
  <template>
206
- <div
207
- class="gl-form-combobox dropdown"
208
- role="combobox"
209
- :aria-owns="suggestionsId"
210
- :aria-expanded="ariaExpanded"
211
- >
216
+ <div class="gl-form-combobox dropdown">
212
217
  <gl-form-group :label="labelText" :label-for="inputId" :label-sr-only="labelSrOnly">
213
218
  <gl-form-input
214
219
  :id="inputId"
220
+ ref="input"
215
221
  :value="displayedValue"
216
222
  type="text"
217
- role="searchbox"
218
- :autocomplete="showAutocomplete"
219
- aria-autocomplete="list"
223
+ role="combobox"
224
+ :aria-expanded="String(isExpanded)"
220
225
  :aria-controls="suggestionsId"
226
+ :aria-owns="isExpanded ? suggestionsId : null"
227
+ aria-autocomplete="list"
221
228
  aria-haspopup="listbox"
229
+ :aria-activedescendant="
230
+ arrowCounter >= 0 ? `${suggestionsId}-option-${arrowCounter}` : undefined
231
+ "
222
232
  :autofocus="autofocus"
223
233
  :placeholder="placeholder"
224
234
  @input="onEntry"
225
235
  @focus="resetCounter"
226
236
  @keydown.down="onArrowDown"
227
237
  @keydown.up="onArrowUp"
238
+ @keydown.left="onArrowLeft"
239
+ @keydown.right="onArrowRight"
228
240
  @keydown.esc.stop="onEsc"
229
241
  @keydown.tab="closeSuggestions"
230
242
  />
231
243
  </gl-form-group>
232
244
 
233
- <ul
234
- v-show="showSuggestions && !userDismissedResults"
245
+ <div
246
+ v-show="isExpanded"
235
247
  :id="suggestionsId"
236
248
  ref="suggestionsMenu"
237
249
  data-testid="combobox-dropdown"
250
+ role="listbox"
238
251
  class="dropdown-menu gl-form-combobox-inner gl-mb-0 gl-flex gl-w-full gl-list-none gl-flex-col gl-border-dropdown gl-bg-dropdown gl-pl-0"
239
252
  @keydown.down="onArrowDown"
240
253
  @keydown.up="onArrowUp"
254
+ @keydown.left="onArrowLeft"
255
+ @keydown.right="onArrowRight"
241
256
  @keydown.esc.stop="onEsc"
242
257
  >
243
- <li class="show-dropdown gl-overflow-y-auto">
244
- <ul class="gl-mb-0 gl-list-none gl-pl-0">
245
- <gl-dropdown-item
246
- v-for="(result, i) in results"
247
- ref="results"
248
- :key="i"
249
- role="option"
250
- :aria-selected="i === arrowCounter"
251
- tabindex="-1"
252
- @click="selectToken(result)"
253
- @keydown.enter.native="selectToken(result)"
254
- >
255
- <!-- @slot The suggestion result item to display. -->
256
- <slot name="result" :item="result">{{ result }}</slot>
257
- </gl-dropdown-item>
258
- </ul>
259
- </li>
260
- <gl-dropdown-divider v-if="resultsLength > 0 && actionList.length > 0" />
261
- <li>
262
- <ul class="gl-mb-0 gl-list-none gl-pl-0">
263
- <gl-dropdown-item
264
- v-for="(action, i) in actionList"
265
- :key="i + resultsLength"
266
- role="option"
267
- :aria-selected="i + resultsLength === arrowCounter"
268
- tabindex="-1"
269
- data-testid="combobox-action"
270
- @click="selectAction(action)"
271
- @keydown.enter.native="selectAction(action)"
272
- >
273
- <!-- @slot The action item to display. -->
274
- <slot name="action" :item="action">{{ action.label }}</slot>
275
- </gl-dropdown-item>
276
- </ul>
277
- </li>
278
- </ul>
258
+ <div class="gl-overflow-y-auto">
259
+ <gl-dropdown-item
260
+ v-for="(result, i) in results"
261
+ :id="`${suggestionsId}-option-${i}`"
262
+ ref="results"
263
+ :key="i"
264
+ :active="i === arrowCounter"
265
+ tabindex="-1"
266
+ role="option"
267
+ data-testid="combobox-result"
268
+ @click="selectToken(result)"
269
+ @keydown.enter.native="selectToken(result)"
270
+ >
271
+ <!-- @slot The suggestion result item to display. -->
272
+ <slot name="result" :item="result">{{ result }}</slot>
273
+ </gl-dropdown-item>
274
+ </div>
275
+
276
+ <gl-dropdown-divider v-if="resultsLength > 0 && actionList.length > 0" aria-hidden="true" />
277
+
278
+ <div>
279
+ <gl-dropdown-item
280
+ v-for="(action, i) in actionList"
281
+ :id="`${suggestionsId}-option-${i + resultsLength}`"
282
+ :key="i + resultsLength"
283
+ :active="i + resultsLength === arrowCounter"
284
+ tabindex="-1"
285
+ role="option"
286
+ data-testid="combobox-action"
287
+ @click="selectAction(action)"
288
+ @keydown.enter.native="selectAction(action)"
289
+ @keydown.left="onArrowLeft"
290
+ @keydown.right="onArrowRight"
291
+ >
292
+ <!-- @slot The action item to display. -->
293
+ <slot name="action" :item="action">{{ action.label }}</slot>
294
+ </gl-dropdown-item>
295
+ </div>
296
+ </div>
279
297
  </div>
280
298
  </template>
@@ -18,7 +18,8 @@ export const props = makePropsConfigurable(
18
18
  activeClass: makeProp(PROP_TYPE_STRING, 'active'),
19
19
  buttonClass: makeProp(PROP_TYPE_ARRAY_OBJECT_STRING),
20
20
  disabled: makeProp(PROP_TYPE_BOOLEAN, false),
21
- variant: makeProp(PROP_TYPE_STRING)
21
+ variant: makeProp(PROP_TYPE_STRING),
22
+ role: makeProp(PROP_TYPE_STRING, 'menuitem')
22
23
  },
23
24
  NAME_DROPDOWN_ITEM_BUTTON
24
25
  )
@@ -42,9 +43,10 @@ export const BDropdownItemButton = /*#__PURE__*/ extend({
42
43
  computedAttrs() {
43
44
  return {
44
45
  ...this.bvAttrs,
45
- role: 'menuitem',
46
+ role: this.role,
46
47
  type: 'button',
47
- disabled: this.disabled
48
+ disabled: this.disabled,
49
+ 'aria-selected': this.active ? 'true' : null
48
50
  }
49
51
  }
50
52
  },