@gitlab/ui 62.10.0 → 62.12.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 +14 -0
- package/dist/components/base/new_dropdowns/disclosure/disclosure_dropdown.js +20 -3
- package/dist/components/base/new_dropdowns/disclosure/disclosure_dropdown_item.js +1 -1
- package/dist/components/base/new_dropdowns/listbox/listbox.js +1 -1
- package/dist/components/base/new_dropdowns/listbox/listbox_group.js +6 -1
- package/package.json +14 -14
- package/src/components/base/new_dropdowns/disclosure/disclosure_dropdown.md +1 -0
- package/src/components/base/new_dropdowns/disclosure/disclosure_dropdown.spec.js +16 -0
- package/src/components/base/new_dropdowns/disclosure/disclosure_dropdown.stories.js +13 -3
- package/src/components/base/new_dropdowns/disclosure/disclosure_dropdown.vue +21 -1
- package/src/components/base/new_dropdowns/disclosure/disclosure_dropdown_item.vue +1 -2
- package/src/components/base/new_dropdowns/listbox/listbox.md +4 -1
- package/src/components/base/new_dropdowns/listbox/listbox.spec.js +14 -0
- package/src/components/base/new_dropdowns/listbox/listbox.vue +6 -1
- package/src/components/base/new_dropdowns/listbox/listbox_group.spec.js +14 -0
- package/src/components/base/new_dropdowns/listbox/listbox_group.vue +6 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
# [62.12.0](https://gitlab.com/gitlab-org/gitlab-ui/compare/v62.11.0...v62.12.0) (2023-05-15)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Features
|
|
5
|
+
|
|
6
|
+
* **GlCollapsibleListbox:** allow groups with no text ([01e709d](https://gitlab.com/gitlab-org/gitlab-ui/commit/01e709d807f49286412939f3ad0c6c75b2ebb40c))
|
|
7
|
+
|
|
8
|
+
# [62.11.0](https://gitlab.com/gitlab-org/gitlab-ui/compare/v62.10.0...v62.11.0) (2023-05-12)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Features
|
|
12
|
+
|
|
13
|
+
* **GlDisclosureDropdown:** Close the disclosure dropdown on item click ([f4c2208](https://gitlab.com/gitlab-org/gitlab-ui/commit/f4c2208af8f11b5aa96faa6bdb88898f67b4edcc))
|
|
14
|
+
|
|
1
15
|
# [62.10.0](https://gitlab.com/gitlab-org/gitlab-ui/compare/v62.9.3...v62.10.0) (2023-05-11)
|
|
2
16
|
|
|
3
17
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import clamp from 'lodash/clamp';
|
|
2
2
|
import uniqueId from 'lodash/uniqueId';
|
|
3
3
|
import { stopEvent, filterVisible } from '../../../../utils/utils';
|
|
4
|
-
import { GL_DROPDOWN_SHOWN, GL_DROPDOWN_HIDDEN, GL_DROPDOWN_FOCUS_CONTENT, HOME, END, ARROW_UP, ARROW_DOWN } from '../constants';
|
|
4
|
+
import { GL_DROPDOWN_SHOWN, GL_DROPDOWN_HIDDEN, GL_DROPDOWN_FOCUS_CONTENT, HOME, END, ARROW_UP, ARROW_DOWN, ENTER, SPACE } from '../constants';
|
|
5
5
|
import { buttonCategoryOptions, dropdownVariantOptions, buttonSizeOptions, dropdownPlacements } from '../../../../utils/constants';
|
|
6
6
|
import GlBaseDropdown from '../base_dropdown/base_dropdown';
|
|
7
7
|
import GlDisclosureDropdownItem, { ITEM_CLASS } from './disclosure_dropdown_item';
|
|
@@ -10,6 +10,7 @@ import { itemsValidator, hasOnlyListItems, isItem } from './utils';
|
|
|
10
10
|
import __vue_normalize__ from 'vue-runtime-helpers/dist/normalize-component.js';
|
|
11
11
|
|
|
12
12
|
//
|
|
13
|
+
const ITEM_SELECTOR = `.${ITEM_CLASS}`;
|
|
13
14
|
var script = {
|
|
14
15
|
name: 'GlDisclosureDropdown',
|
|
15
16
|
events: {
|
|
@@ -169,6 +170,14 @@ var script = {
|
|
|
169
170
|
type: Boolean,
|
|
170
171
|
required: false,
|
|
171
172
|
default: false
|
|
173
|
+
},
|
|
174
|
+
/**
|
|
175
|
+
* Close the dropdown on item click (action)
|
|
176
|
+
*/
|
|
177
|
+
autoClose: {
|
|
178
|
+
type: Boolean,
|
|
179
|
+
required: false,
|
|
180
|
+
default: true
|
|
172
181
|
}
|
|
173
182
|
},
|
|
174
183
|
data() {
|
|
@@ -228,6 +237,8 @@ var script = {
|
|
|
228
237
|
this.focusNextItem(event, elements, -1);
|
|
229
238
|
} else if (code === ARROW_DOWN) {
|
|
230
239
|
this.focusNextItem(event, elements, 1);
|
|
240
|
+
} else if (code === ENTER || code === SPACE) {
|
|
241
|
+
this.handleAutoClose(event);
|
|
231
242
|
} else {
|
|
232
243
|
stop = false;
|
|
233
244
|
}
|
|
@@ -237,7 +248,7 @@ var script = {
|
|
|
237
248
|
},
|
|
238
249
|
getFocusableListItemElements() {
|
|
239
250
|
var _this$$refs$content;
|
|
240
|
-
const items = (_this$$refs$content = this.$refs.content) === null || _this$$refs$content === void 0 ? void 0 : _this$$refs$content.querySelectorAll(
|
|
251
|
+
const items = (_this$$refs$content = this.$refs.content) === null || _this$$refs$content === void 0 ? void 0 : _this$$refs$content.querySelectorAll(ITEM_SELECTOR);
|
|
241
252
|
return filterVisible(Array.from(items || []));
|
|
242
253
|
},
|
|
243
254
|
focusNextItem(event, elements, offset) {
|
|
@@ -264,6 +275,11 @@ var script = {
|
|
|
264
275
|
*/
|
|
265
276
|
this.$emit('action', action);
|
|
266
277
|
},
|
|
278
|
+
handleAutoClose(e) {
|
|
279
|
+
if (this.autoClose && e.target.closest(ITEM_SELECTOR)) {
|
|
280
|
+
this.closeAndFocus();
|
|
281
|
+
}
|
|
282
|
+
},
|
|
267
283
|
uniqueItemId() {
|
|
268
284
|
return uniqueId(`disclosure-item-`);
|
|
269
285
|
},
|
|
@@ -275,7 +291,7 @@ var script = {
|
|
|
275
291
|
const __vue_script__ = script;
|
|
276
292
|
|
|
277
293
|
/* template */
|
|
278
|
-
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,"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,"popper-options":_vm.popperOptions,"fluid-width":_vm.fluidWidth},on:_vm._d({},[_vm.$options.events.GL_DROPDOWN_SHOWN,_vm.onShow,_vm.$options.events.GL_DROPDOWN_HIDDEN,_vm.onHide,_vm.$options.events.GL_DROPDOWN_FOCUS_CONTENT,_vm.onKeydown]),scopedSlots:_vm._u([(_vm.hasCustomToggle)?{key:"toggle",fn:function(){return [_vm._t("toggle")]},proxy:true}:null],null,true)},[_vm._v(" "),_vm._t("header"),_vm._v(" "),_c(_vm.disclosureTag,{ref:"content",tag:"component",staticClass:"gl-new-dropdown-contents",attrs:{"id":_vm.disclosureId,"aria-labelledby":_vm.listAriaLabelledBy || _vm.toggleId,"data-testid":"disclosure-content","tabindex":"-1"},on:{"keydown":_vm.onKeydown}},[_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:{"item":item},on:{"action":_vm.handleAction},scopedSlots:_vm._u([{key:"list-item",fn:function(){return [_vm._t("list-item",null,{"item":item})]},proxy:true}],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],null,true)},[_vm._v(" "),(_vm.$scopedSlots['list-item'])?_vm._l((item.items),function(groupItem){return _c('gl-disclosure-dropdown-item',{key:_vm.uniqueItemId(),attrs:{"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)})}):_vm._e()],2)]]})]})],2),_vm._v(" "),_vm._t("footer")],2)};
|
|
294
|
+
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,"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,"popper-options":_vm.popperOptions,"fluid-width":_vm.fluidWidth},on:_vm._d({},[_vm.$options.events.GL_DROPDOWN_SHOWN,_vm.onShow,_vm.$options.events.GL_DROPDOWN_HIDDEN,_vm.onHide,_vm.$options.events.GL_DROPDOWN_FOCUS_CONTENT,_vm.onKeydown]),scopedSlots:_vm._u([(_vm.hasCustomToggle)?{key:"toggle",fn:function(){return [_vm._t("toggle")]},proxy:true}:null],null,true)},[_vm._v(" "),_vm._t("header"),_vm._v(" "),_c(_vm.disclosureTag,{ref:"content",tag:"component",staticClass:"gl-new-dropdown-contents",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:{"item":item},on:{"action":_vm.handleAction},scopedSlots:_vm._u([{key:"list-item",fn:function(){return [_vm._t("list-item",null,{"item":item})]},proxy:true}],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],null,true)},[_vm._v(" "),(_vm.$scopedSlots['list-item'])?_vm._l((item.items),function(groupItem){return _c('gl-disclosure-dropdown-item',{key:_vm.uniqueItemId(),attrs:{"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)})}):_vm._e()],2)]]})]})],2),_vm._v(" "),_vm._t("footer")],2)};
|
|
279
295
|
var __vue_staticRenderFns__ = [];
|
|
280
296
|
|
|
281
297
|
/* style */
|
|
@@ -308,3 +324,4 @@ var __vue_staticRenderFns__ = [];
|
|
|
308
324
|
);
|
|
309
325
|
|
|
310
326
|
export default __vue_component__;
|
|
327
|
+
export { ITEM_SELECTOR };
|
|
@@ -79,11 +79,11 @@ var script = {
|
|
|
79
79
|
code
|
|
80
80
|
} = event;
|
|
81
81
|
if (code === ENTER || code === SPACE) {
|
|
82
|
-
stopEvent(event);
|
|
83
82
|
if (this.isCustomContent) {
|
|
84
83
|
this.action();
|
|
85
84
|
} else {
|
|
86
85
|
var _this$$refs$item;
|
|
86
|
+
stopEvent(event);
|
|
87
87
|
/** Instead of simply navigating or calling the action, we want
|
|
88
88
|
* the `a/button` to be the target of the event as it might have additional attributes.
|
|
89
89
|
* E.g. `a` might have `target` attribute.
|
|
@@ -572,7 +572,7 @@ var script = {
|
|
|
572
572
|
const __vue_script__ = script;
|
|
573
573
|
|
|
574
574
|
/* template */
|
|
575
|
-
var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('gl-base-dropdown',{ref:"baseDropdown",attrs:{"aria-haspopup":"listbox","aria-labelledby":_vm.toggleAriaLabelledBy,"block":_vm.block,"toggle-id":_vm.toggleId,"toggle-text":_vm.listboxToggleText,"toggle-class":_vm.toggleButtonClasses,"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,"popper-options":_vm.popperOptions,"fluid-width":_vm.fluidWidth},on:_vm._d({},[_vm.$options.events.GL_DROPDOWN_SHOWN,_vm.onShow,_vm.$options.events.GL_DROPDOWN_HIDDEN,_vm.onHide]),scopedSlots:_vm._u([(_vm.hasCustomToggle)?{key:"toggle",fn:function(){return [_vm._t("toggle")]},proxy:true}:null],null,true)},[_vm._v(" "),(_vm.headerText)?_c('div',{staticClass:"gl-display-flex gl-align-items-center gl-p-4! gl-min-h-8",class:_vm.$options.HEADER_ITEMS_BORDER_CLASSES},[_c('div',{staticClass:"gl-flex-grow-1 gl-font-weight-bold gl-font-sm gl-pr-2",attrs:{"id":_vm.headerId,"data-testid":"listbox-header-text"}},[_vm._v("\n "+_vm._s(_vm.headerText)+"\n ")]),_vm._v(" "),(_vm.showResetButton)?_c('gl-button',{staticClass:"gl-focus-inset-border-2-blue-400! gl-flex-shrink-0 gl-font-sm! gl-px-2! gl-py-2! gl-w-auto! gl-m-0!",attrs:{"category":"tertiary","data-testid":"listbox-reset-button"},on:{"click":_vm.onResetButtonClicked}},[_vm._v("\n "+_vm._s(_vm.resetButtonLabel)+"\n ")]):_vm._e()],1):_vm._e(),_vm._v(" "),(_vm.searchable)?_c('div',{class:_vm.$options.HEADER_ITEMS_BORDER_CLASSES},[_c('gl-listbox-search-input',{ref:"searchBox",attrs:{"aria-owns":_vm.listboxId,"data-testid":"listbox-search-input","placeholder":_vm.searchPlaceholder},on:{"input":_vm.search,"keydown":[function($event){if(!$event.type.indexOf('key')&&_vm._k($event.keyCode,"enter",13,$event.key,"Enter")){ return null; }$event.preventDefault();},_vm.onKeydown]},model:{value:(_vm.searchStr),callback:function ($$v) {_vm.searchStr=$$v;},expression:"searchStr"}}),_vm._v(" "),(_vm.searching)?_c('gl-loading-icon',{staticClass:"gl-my-3",attrs:{"data-testid":"listbox-search-loader","size":"md"}}):_vm._e()],1):_vm._e(),_vm._v(" "),(_vm.showList)?_c(_vm.listboxTag,{ref:"list",tag:"component",staticClass:"gl-new-dropdown-contents",attrs:{"id":_vm.listboxId,"aria-labelledby":_vm.listAriaLabelledBy || _vm.headerId || _vm.toggleId,"role":"listbox","tabindex":"-1"},on:{"keydown":_vm.onKeydown}},[_vm._l((_vm.items),function(item,index){return [(_vm.isOption(item))?[_c('gl-listbox-item',_vm._b({key:item.value,attrs:{"data-testid":("listbox-item-" + (item.value)),"is-selected":_vm.isSelected(item),"is-focused":_vm.isFocused(item),"is-check-centered":_vm.isCheckCentered},on:{"select":function($event){return _vm.onSelect(item, $event)}}},'gl-listbox-item',_vm.listboxItemMoreItemsAriaAttributes(index),false),[_vm._t("list-item",function(){return [_vm._v("\n "+_vm._s(item.text)+"\n ")]},{"item":item})],2)]:[_c('gl-listbox-group',{key:item.text,class:_vm.groupClasses(index),attrs:{"name":item.text},scopedSlots:_vm._u([(_vm.$scopedSlots['group-label'])?{key:"group-label",fn:function(){return [_vm._t("group-label",null,{"group":item})]},proxy:true}:null],null,true)},[_vm._v(" "),_vm._l((item.options),function(option){return _c('gl-listbox-item',{key:option.value,attrs:{"data-testid":("listbox-item-" + (option.value)),"is-selected":_vm.isSelected(option),"is-focused":_vm.isFocused(option),"is-check-centered":_vm.isCheckCentered},on:{"select":function($event){return _vm.onSelect(option, $event)}}},[_vm._t("list-item",function(){return [_vm._v("\n "+_vm._s(option.text)+"\n ")]},{"item":option})],2)})],2)]]}),_vm._v(" "),(_vm.infiniteScrollLoading)?_c(_vm.listboxTag === 'ul' ? 'li' : 'div',{tag:"component"},[_c('gl-loading-icon',{staticClass:"gl-my-3",attrs:{"data-testid":"listbox-infinite-scroll-loader","size":"md"}})],1):_vm._e(),_vm._v(" "),(_vm.showIntersectionObserver)?_c('gl-intersection-observer',{on:{"appear":_vm.onIntersectionObserverAppear}}):_vm._e()],2):_vm._e(),_vm._v(" "),(_vm.announceSRSearchResults)?_c('span',{staticClass:"gl-sr-only",attrs:{"data-testid":"listbox-number-of-results","aria-live":"assertive"}},[_vm._t("search-summary-sr-only")],2):(_vm.showNoResultsText)?_c('div',{staticClass:"gl-pl-7 gl-pr-5 gl-py-3 gl-font-base gl-text-gray-600",attrs:{"aria-live":"assertive","data-testid":"listbox-no-results-text"}},[_vm._v("\n "+_vm._s(_vm.noResultsText)+"\n ")]):_vm._e(),_vm._v(" "),_vm._t("footer")],2)};
|
|
575
|
+
var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('gl-base-dropdown',{ref:"baseDropdown",attrs:{"aria-haspopup":"listbox","aria-labelledby":_vm.toggleAriaLabelledBy,"block":_vm.block,"toggle-id":_vm.toggleId,"toggle-text":_vm.listboxToggleText,"toggle-class":_vm.toggleButtonClasses,"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,"popper-options":_vm.popperOptions,"fluid-width":_vm.fluidWidth},on:_vm._d({},[_vm.$options.events.GL_DROPDOWN_SHOWN,_vm.onShow,_vm.$options.events.GL_DROPDOWN_HIDDEN,_vm.onHide]),scopedSlots:_vm._u([(_vm.hasCustomToggle)?{key:"toggle",fn:function(){return [_vm._t("toggle")]},proxy:true}:null],null,true)},[_vm._v(" "),(_vm.headerText)?_c('div',{staticClass:"gl-display-flex gl-align-items-center gl-p-4! gl-min-h-8",class:_vm.$options.HEADER_ITEMS_BORDER_CLASSES},[_c('div',{staticClass:"gl-flex-grow-1 gl-font-weight-bold gl-font-sm gl-pr-2",attrs:{"id":_vm.headerId,"data-testid":"listbox-header-text"}},[_vm._v("\n "+_vm._s(_vm.headerText)+"\n ")]),_vm._v(" "),(_vm.showResetButton)?_c('gl-button',{staticClass:"gl-focus-inset-border-2-blue-400! gl-flex-shrink-0 gl-font-sm! gl-px-2! gl-py-2! gl-w-auto! gl-m-0!",attrs:{"category":"tertiary","data-testid":"listbox-reset-button"},on:{"click":_vm.onResetButtonClicked}},[_vm._v("\n "+_vm._s(_vm.resetButtonLabel)+"\n ")]):_vm._e()],1):_vm._e(),_vm._v(" "),(_vm.searchable)?_c('div',{class:_vm.$options.HEADER_ITEMS_BORDER_CLASSES},[_c('gl-listbox-search-input',{ref:"searchBox",attrs:{"aria-owns":_vm.listboxId,"data-testid":"listbox-search-input","placeholder":_vm.searchPlaceholder},on:{"input":_vm.search,"keydown":[function($event){if(!$event.type.indexOf('key')&&_vm._k($event.keyCode,"enter",13,$event.key,"Enter")){ return null; }$event.preventDefault();},_vm.onKeydown]},model:{value:(_vm.searchStr),callback:function ($$v) {_vm.searchStr=$$v;},expression:"searchStr"}}),_vm._v(" "),(_vm.searching)?_c('gl-loading-icon',{staticClass:"gl-my-3",attrs:{"data-testid":"listbox-search-loader","size":"md"}}):_vm._e()],1):_vm._e(),_vm._v(" "),(_vm.showList)?_c(_vm.listboxTag,{ref:"list",tag:"component",staticClass:"gl-new-dropdown-contents",attrs:{"id":_vm.listboxId,"aria-labelledby":_vm.listAriaLabelledBy || _vm.headerId || _vm.toggleId,"role":"listbox","tabindex":"-1"},on:{"keydown":_vm.onKeydown}},[_vm._l((_vm.items),function(item,index){return [(_vm.isOption(item))?[_c('gl-listbox-item',_vm._b({key:item.value,attrs:{"data-testid":("listbox-item-" + (item.value)),"is-selected":_vm.isSelected(item),"is-focused":_vm.isFocused(item),"is-check-centered":_vm.isCheckCentered},on:{"select":function($event){return _vm.onSelect(item, $event)}}},'gl-listbox-item',_vm.listboxItemMoreItemsAriaAttributes(index),false),[_vm._t("list-item",function(){return [_vm._v("\n "+_vm._s(item.text)+"\n ")]},{"item":item})],2)]:[_c('gl-listbox-group',{key:item.text,class:_vm.groupClasses(index),attrs:{"name":item.text,"text-sr-only":item.textSrOnly},scopedSlots:_vm._u([(_vm.$scopedSlots['group-label'])?{key:"group-label",fn:function(){return [_vm._t("group-label",null,{"group":item})]},proxy:true}:null],null,true)},[_vm._v(" "),_vm._l((item.options),function(option){return _c('gl-listbox-item',{key:option.value,attrs:{"data-testid":("listbox-item-" + (option.value)),"is-selected":_vm.isSelected(option),"is-focused":_vm.isFocused(option),"is-check-centered":_vm.isCheckCentered},on:{"select":function($event){return _vm.onSelect(option, $event)}}},[_vm._t("list-item",function(){return [_vm._v("\n "+_vm._s(option.text)+"\n ")]},{"item":option})],2)})],2)]]}),_vm._v(" "),(_vm.infiniteScrollLoading)?_c(_vm.listboxTag === 'ul' ? 'li' : 'div',{tag:"component"},[_c('gl-loading-icon',{staticClass:"gl-my-3",attrs:{"data-testid":"listbox-infinite-scroll-loader","size":"md"}})],1):_vm._e(),_vm._v(" "),(_vm.showIntersectionObserver)?_c('gl-intersection-observer',{on:{"appear":_vm.onIntersectionObserverAppear}}):_vm._e()],2):_vm._e(),_vm._v(" "),(_vm.announceSRSearchResults)?_c('span',{staticClass:"gl-sr-only",attrs:{"data-testid":"listbox-number-of-results","aria-live":"assertive"}},[_vm._t("search-summary-sr-only")],2):(_vm.showNoResultsText)?_c('div',{staticClass:"gl-pl-7 gl-pr-5 gl-py-3 gl-font-base gl-text-gray-600",attrs:{"aria-live":"assertive","data-testid":"listbox-no-results-text"}},[_vm._v("\n "+_vm._s(_vm.noResultsText)+"\n ")]):_vm._e(),_vm._v(" "),_vm._t("footer")],2)};
|
|
576
576
|
var __vue_staticRenderFns__ = [];
|
|
577
577
|
|
|
578
578
|
/* style */
|
|
@@ -7,6 +7,11 @@ var script = {
|
|
|
7
7
|
name: {
|
|
8
8
|
type: String,
|
|
9
9
|
required: true
|
|
10
|
+
},
|
|
11
|
+
textSrOnly: {
|
|
12
|
+
type: Boolean,
|
|
13
|
+
required: false,
|
|
14
|
+
default: false
|
|
10
15
|
}
|
|
11
16
|
},
|
|
12
17
|
created() {
|
|
@@ -18,7 +23,7 @@ var script = {
|
|
|
18
23
|
const __vue_script__ = script;
|
|
19
24
|
|
|
20
25
|
/* template */
|
|
21
|
-
var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('ul',{staticClass:"gl-mb-0 gl-pl-0",attrs:{"role":"group","aria-labelledby":_vm.nameId}},[_c('li',{staticClass:"gl-pl-4 gl-pt-3 gl-pb-2 gl-font-sm gl-font-weight-bold",attrs:{"id":_vm.nameId,"role":"presentation"}},[_vm._t("group-label",function(){return [_vm._v(_vm._s(_vm.name))]})],2),_vm._v(" "),_vm._t("default")],2)};
|
|
26
|
+
var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('ul',{staticClass:"gl-mb-0 gl-pl-0",attrs:{"role":"group","aria-labelledby":_vm.nameId}},[_c('li',{staticClass:"gl-pl-4 gl-pt-3 gl-pb-2 gl-font-sm gl-font-weight-bold",class:{ 'gl-sr-only': _vm.textSrOnly },attrs:{"id":_vm.nameId,"role":"presentation"}},[_vm._t("group-label",function(){return [_vm._v(_vm._s(_vm.name))]})],2),_vm._v(" "),_vm._t("default")],2)};
|
|
22
27
|
var __vue_staticRenderFns__ = [];
|
|
23
28
|
|
|
24
29
|
/* style */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gitlab/ui",
|
|
3
|
-
"version": "62.
|
|
3
|
+
"version": "62.12.0",
|
|
4
4
|
"description": "GitLab UI Components",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -89,22 +89,22 @@
|
|
|
89
89
|
"@gitlab/eslint-plugin": "19.0.0",
|
|
90
90
|
"@gitlab/fonts": "^1.2.0",
|
|
91
91
|
"@gitlab/stylelint-config": "4.1.0",
|
|
92
|
-
"@gitlab/svgs": "3.
|
|
92
|
+
"@gitlab/svgs": "3.46.0",
|
|
93
93
|
"@rollup/plugin-commonjs": "^11.1.0",
|
|
94
94
|
"@rollup/plugin-node-resolve": "^7.1.3",
|
|
95
95
|
"@rollup/plugin-replace": "^2.3.2",
|
|
96
|
-
"@storybook/addon-a11y": "7.0.
|
|
97
|
-
"@storybook/addon-docs": "7.0.
|
|
98
|
-
"@storybook/addon-essentials": "7.0.
|
|
99
|
-
"@storybook/addon-storyshots": "7.0.
|
|
100
|
-
"@storybook/addon-storyshots-puppeteer": "7.0.
|
|
101
|
-
"@storybook/addon-viewport": "7.0.
|
|
102
|
-
"@storybook/builder-webpack5": "7.0.
|
|
103
|
-
"@storybook/theming": "7.0.
|
|
104
|
-
"@storybook/vue": "7.0.
|
|
105
|
-
"@storybook/vue-webpack5": "7.0.
|
|
106
|
-
"@storybook/vue3": "7.0.
|
|
107
|
-
"@storybook/vue3-webpack5": "7.0.
|
|
96
|
+
"@storybook/addon-a11y": "7.0.11",
|
|
97
|
+
"@storybook/addon-docs": "7.0.11",
|
|
98
|
+
"@storybook/addon-essentials": "7.0.11",
|
|
99
|
+
"@storybook/addon-storyshots": "7.0.11",
|
|
100
|
+
"@storybook/addon-storyshots-puppeteer": "7.0.11",
|
|
101
|
+
"@storybook/addon-viewport": "7.0.11",
|
|
102
|
+
"@storybook/builder-webpack5": "7.0.11",
|
|
103
|
+
"@storybook/theming": "7.0.11",
|
|
104
|
+
"@storybook/vue": "7.0.11",
|
|
105
|
+
"@storybook/vue-webpack5": "7.0.11",
|
|
106
|
+
"@storybook/vue3": "7.0.11",
|
|
107
|
+
"@storybook/vue3-webpack5": "7.0.11",
|
|
108
108
|
"@vue/compat": "^3.2.40",
|
|
109
109
|
"@vue/compiler-sfc": "^3.2.40",
|
|
110
110
|
"@vue/test-utils": "1.3.0",
|
|
@@ -323,4 +323,20 @@ describe('GlDisclosureDropdown', () => {
|
|
|
323
323
|
expect(findBaseDropdown().props('fluidWidth')).toBe(true);
|
|
324
324
|
});
|
|
325
325
|
});
|
|
326
|
+
|
|
327
|
+
describe('auto closing', () => {
|
|
328
|
+
it('closes the dropdown when `autoClose` is set on item click', () => {
|
|
329
|
+
buildWrapper({ items: mockItems });
|
|
330
|
+
const closeSpy = jest.spyOn(wrapper.vm.$refs.baseDropdown, 'closeAndFocus');
|
|
331
|
+
findListItem(0).trigger('click');
|
|
332
|
+
expect(closeSpy).toHaveBeenCalled();
|
|
333
|
+
});
|
|
334
|
+
|
|
335
|
+
it('does not close the dropdown on item click when `autoClose` is set to `false`', () => {
|
|
336
|
+
buildWrapper({ items: mockItems, autoClose: false });
|
|
337
|
+
const closeSpy = jest.spyOn(wrapper.vm.$refs.baseDropdown, 'closeAndFocus');
|
|
338
|
+
findListItem(0).trigger('click');
|
|
339
|
+
expect(closeSpy).not.toHaveBeenCalled();
|
|
340
|
+
});
|
|
341
|
+
});
|
|
326
342
|
});
|
|
@@ -40,6 +40,7 @@ const makeBindings = (overrides = {}) =>
|
|
|
40
40
|
':toggle-aria-labelled-by': 'toggleAriaLabelledBy',
|
|
41
41
|
':list-aria-labelled-by': 'listAriaLabelledBy',
|
|
42
42
|
':fluid-width': 'fluidWidth',
|
|
43
|
+
':auto-close': 'autoClose',
|
|
43
44
|
...overrides,
|
|
44
45
|
})
|
|
45
46
|
.map(([key, value]) => `${key}="${value}"`)
|
|
@@ -216,7 +217,7 @@ export const CustomGroupsItemsAndToggle = makeGroupedExample({
|
|
|
216
217
|
</button>
|
|
217
218
|
</template>
|
|
218
219
|
<gl-disclosure-dropdown-group>
|
|
219
|
-
<gl-disclosure-dropdown-item>
|
|
220
|
+
<gl-disclosure-dropdown-item @action="closeDropdown">
|
|
220
221
|
<template #list-item>
|
|
221
222
|
<span class="gl-display-flex gl-flex-direction-column">
|
|
222
223
|
<span class="gl-font-weight-bold gl-white-space-nowrap">Orange Fox</span>
|
|
@@ -225,7 +226,7 @@ export const CustomGroupsItemsAndToggle = makeGroupedExample({
|
|
|
225
226
|
</template>
|
|
226
227
|
</gl-disclosure-dropdown-item>
|
|
227
228
|
</gl-disclosure-dropdown-group>
|
|
228
|
-
<gl-disclosure-dropdown-group bordered :group="$options.groups[0]">
|
|
229
|
+
<gl-disclosure-dropdown-group bordered :group="$options.groups[0]" @action="closeDropdown">
|
|
229
230
|
<template #list-item="{ item }">
|
|
230
231
|
<span class="gl-display-flex gl-align-items-center gl-justify-content-space-between">
|
|
231
232
|
{{item.text}}
|
|
@@ -249,7 +250,7 @@ export const CustomGroupsItemsAndToggle = makeGroupedExample({
|
|
|
249
250
|
<template #list-item>Provide feedback</template>
|
|
250
251
|
</gl-disclosure-dropdown-item>
|
|
251
252
|
</gl-disclosure-dropdown-group>
|
|
252
|
-
<gl-disclosure-dropdown-group bordered :group="$options.groups[1]"/>
|
|
253
|
+
<gl-disclosure-dropdown-group bordered :group="$options.groups[1]" @action="closeDropdown"/>
|
|
253
254
|
`,
|
|
254
255
|
{
|
|
255
256
|
after: `
|
|
@@ -266,11 +267,19 @@ export const CustomGroupsItemsAndToggle = makeGroupedExample({
|
|
|
266
267
|
};
|
|
267
268
|
},
|
|
268
269
|
methods: {
|
|
270
|
+
closeDropdown() {
|
|
271
|
+
this.$refs.disclosure.closeAndFocus();
|
|
272
|
+
},
|
|
269
273
|
toggleModalVisibility(value) {
|
|
270
274
|
this.feedBackModalVisible = value;
|
|
275
|
+
this.closeDropdown();
|
|
271
276
|
},
|
|
272
277
|
toggleNewNavigation() {
|
|
273
278
|
this.newNavigation = !this.newNavigation;
|
|
279
|
+
// eslint-disable-next-line no-restricted-globals
|
|
280
|
+
setTimeout(() => {
|
|
281
|
+
this.closeDropdown();
|
|
282
|
+
}, 500);
|
|
274
283
|
},
|
|
275
284
|
},
|
|
276
285
|
groups: mockProfileGroups,
|
|
@@ -279,6 +288,7 @@ CustomGroupsItemsAndToggle.args = {
|
|
|
279
288
|
icon: 'plus-square',
|
|
280
289
|
toggleText: 'User profile menu',
|
|
281
290
|
textSrOnly: true,
|
|
291
|
+
autoClose: false,
|
|
282
292
|
};
|
|
283
293
|
CustomGroupsItemsAndToggle.decorators = [makeContainer({ height: '400px' })];
|
|
284
294
|
|
|
@@ -7,6 +7,8 @@ import {
|
|
|
7
7
|
GL_DROPDOWN_SHOWN,
|
|
8
8
|
GL_DROPDOWN_HIDDEN,
|
|
9
9
|
GL_DROPDOWN_FOCUS_CONTENT,
|
|
10
|
+
ENTER,
|
|
11
|
+
SPACE,
|
|
10
12
|
HOME,
|
|
11
13
|
END,
|
|
12
14
|
ARROW_DOWN,
|
|
@@ -23,6 +25,8 @@ import GlDisclosureDropdownItem, { ITEM_CLASS } from './disclosure_dropdown_item
|
|
|
23
25
|
import GlDisclosureDropdownGroup from './disclosure_dropdown_group.vue';
|
|
24
26
|
import { itemsValidator, isItem, hasOnlyListItems } from './utils';
|
|
25
27
|
|
|
28
|
+
export const ITEM_SELECTOR = `.${ITEM_CLASS}`;
|
|
29
|
+
|
|
26
30
|
export default {
|
|
27
31
|
name: 'GlDisclosureDropdown',
|
|
28
32
|
events: {
|
|
@@ -183,6 +187,14 @@ export default {
|
|
|
183
187
|
required: false,
|
|
184
188
|
default: false,
|
|
185
189
|
},
|
|
190
|
+
/**
|
|
191
|
+
* Close the dropdown on item click (action)
|
|
192
|
+
*/
|
|
193
|
+
autoClose: {
|
|
194
|
+
type: Boolean,
|
|
195
|
+
required: false,
|
|
196
|
+
default: true,
|
|
197
|
+
},
|
|
186
198
|
},
|
|
187
199
|
data() {
|
|
188
200
|
return {
|
|
@@ -241,6 +253,8 @@ export default {
|
|
|
241
253
|
this.focusNextItem(event, elements, -1);
|
|
242
254
|
} else if (code === ARROW_DOWN) {
|
|
243
255
|
this.focusNextItem(event, elements, 1);
|
|
256
|
+
} else if (code === ENTER || code === SPACE) {
|
|
257
|
+
this.handleAutoClose(event);
|
|
244
258
|
} else {
|
|
245
259
|
stop = false;
|
|
246
260
|
}
|
|
@@ -250,7 +264,7 @@ export default {
|
|
|
250
264
|
}
|
|
251
265
|
},
|
|
252
266
|
getFocusableListItemElements() {
|
|
253
|
-
const items = this.$refs.content?.querySelectorAll(
|
|
267
|
+
const items = this.$refs.content?.querySelectorAll(ITEM_SELECTOR);
|
|
254
268
|
return filterVisible(Array.from(items || []));
|
|
255
269
|
},
|
|
256
270
|
focusNextItem(event, elements, offset) {
|
|
@@ -276,6 +290,11 @@ export default {
|
|
|
276
290
|
*/
|
|
277
291
|
this.$emit('action', action);
|
|
278
292
|
},
|
|
293
|
+
handleAutoClose(e) {
|
|
294
|
+
if (this.autoClose && e.target.closest(ITEM_SELECTOR)) {
|
|
295
|
+
this.closeAndFocus();
|
|
296
|
+
}
|
|
297
|
+
},
|
|
279
298
|
uniqueItemId() {
|
|
280
299
|
return uniqueId(`disclosure-item-`);
|
|
281
300
|
},
|
|
@@ -324,6 +343,7 @@ export default {
|
|
|
324
343
|
class="gl-new-dropdown-contents"
|
|
325
344
|
tabindex="-1"
|
|
326
345
|
@keydown="onKeydown"
|
|
346
|
+
@click="handleAutoClose"
|
|
327
347
|
>
|
|
328
348
|
<slot>
|
|
329
349
|
<template v-for="(item, index) in items">
|
|
@@ -76,11 +76,10 @@ export default {
|
|
|
76
76
|
const { code } = event;
|
|
77
77
|
|
|
78
78
|
if (code === ENTER || code === SPACE) {
|
|
79
|
-
stopEvent(event);
|
|
80
|
-
|
|
81
79
|
if (this.isCustomContent) {
|
|
82
80
|
this.action();
|
|
83
81
|
} else {
|
|
82
|
+
stopEvent(event);
|
|
84
83
|
/** Instead of simply navigating or calling the action, we want
|
|
85
84
|
* the `a/button` to be the target of the event as it might have additional attributes.
|
|
86
85
|
* E.g. `a` might have `target` attribute.
|
|
@@ -71,6 +71,7 @@ type Option = {
|
|
|
71
71
|
type Group = {
|
|
72
72
|
text: string
|
|
73
73
|
options: Array<Option>
|
|
74
|
+
textSrOnly?: boolean
|
|
74
75
|
}
|
|
75
76
|
|
|
76
77
|
type ItemsProp = Array<Option> | Array<Group>
|
|
@@ -104,7 +105,9 @@ template. If you want to render a custom template for items, use the
|
|
|
104
105
|
Options can be contained within groups. A group has a required `text`
|
|
105
106
|
property, which must be unique across all groups within the listbox, as
|
|
106
107
|
it's used as a primary key. It also has a required property `items` that
|
|
107
|
-
must be an array of options.
|
|
108
|
+
must be an array of options. Optionally, you can hide the group heading
|
|
109
|
+
by setting `textSrOnly` to `true`. In this case the `text` is only used
|
|
110
|
+
for accessibility purposes.
|
|
108
111
|
|
|
109
112
|
Groups can be at most one level deep: a group can only contain options.
|
|
110
113
|
Options and groups _cannot_ be siblings. Either all items are options,
|
|
@@ -387,6 +387,20 @@ describe('GlCollapsibleListbox', () => {
|
|
|
387
387
|
expect(findListboxItems(groups.at(i))).toHaveLength(group.options.length);
|
|
388
388
|
});
|
|
389
389
|
});
|
|
390
|
+
|
|
391
|
+
it('passes the `textSrOnly` prop', () => {
|
|
392
|
+
const mockGroupsWithTextSrOnly = JSON.parse(JSON.stringify(mockGroups));
|
|
393
|
+
mockGroupsWithTextSrOnly[0].textSrOnly = true;
|
|
394
|
+
mockGroupsWithTextSrOnly[1].textSrOnly = false;
|
|
395
|
+
buildWrapper({ items: mockGroupsWithTextSrOnly });
|
|
396
|
+
|
|
397
|
+
const groups = findListboxGroups();
|
|
398
|
+
|
|
399
|
+
const expectedTextSrOnlyProps = mockGroupsWithTextSrOnly.map((group) => group.textSrOnly);
|
|
400
|
+
const actualTextSrOnlyProps = groups.wrappers.map((group) => group.props('textSrOnly'));
|
|
401
|
+
|
|
402
|
+
expect(actualTextSrOnlyProps).toEqual(expectedTextSrOnlyProps);
|
|
403
|
+
});
|
|
390
404
|
});
|
|
391
405
|
|
|
392
406
|
describe('when `searchable` is enabled', () => {
|
|
@@ -686,7 +686,12 @@ export default {
|
|
|
686
686
|
</template>
|
|
687
687
|
|
|
688
688
|
<template v-else>
|
|
689
|
-
<gl-listbox-group
|
|
689
|
+
<gl-listbox-group
|
|
690
|
+
:key="item.text"
|
|
691
|
+
:name="item.text"
|
|
692
|
+
:text-sr-only="item.textSrOnly"
|
|
693
|
+
:class="groupClasses(index)"
|
|
694
|
+
>
|
|
690
695
|
<template v-if="$scopedSlots['group-label']" #group-label>
|
|
691
696
|
<!-- @slot Custom template for group names -->
|
|
692
697
|
<slot name="group-label" :group="item"></slot>
|
|
@@ -44,4 +44,18 @@ describe('GlListboxGroup', () => {
|
|
|
44
44
|
|
|
45
45
|
expect(findByTestId('custom-name', findLabelElement()).exists()).toBe(true);
|
|
46
46
|
});
|
|
47
|
+
|
|
48
|
+
describe('`textSrOnly` is true', () => {
|
|
49
|
+
beforeEach(() => {
|
|
50
|
+
buildWrapper({
|
|
51
|
+
propsData: {
|
|
52
|
+
textSrOnly: true,
|
|
53
|
+
},
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it('adds `gl-sr-only` class', () => {
|
|
58
|
+
expect(findLabelElement().classes('gl-sr-only')).toBe(true);
|
|
59
|
+
});
|
|
60
|
+
});
|
|
47
61
|
});
|
|
@@ -8,6 +8,11 @@ export default {
|
|
|
8
8
|
type: String,
|
|
9
9
|
required: true,
|
|
10
10
|
},
|
|
11
|
+
textSrOnly: {
|
|
12
|
+
type: Boolean,
|
|
13
|
+
required: false,
|
|
14
|
+
default: false,
|
|
15
|
+
},
|
|
11
16
|
},
|
|
12
17
|
created() {
|
|
13
18
|
this.nameId = uniqueId('gl-listbox-group-');
|
|
@@ -21,6 +26,7 @@ export default {
|
|
|
21
26
|
:id="nameId"
|
|
22
27
|
role="presentation"
|
|
23
28
|
class="gl-pl-4 gl-pt-3 gl-pb-2 gl-font-sm gl-font-weight-bold"
|
|
29
|
+
:class="{ 'gl-sr-only': textSrOnly }"
|
|
24
30
|
>
|
|
25
31
|
<slot name="group-label">{{ name }}</slot>
|
|
26
32
|
</li>
|