@gitlab/ui 58.2.0 → 58.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 +7 -0
- package/dist/components/base/new_dropdowns/base_dropdown/base_dropdown.js +18 -3
- package/dist/components/base/new_dropdowns/constants.js +2 -1
- package/dist/components/base/new_dropdowns/disclosure/disclosure_dropdown.js +4 -8
- package/package.json +3 -3
- package/src/components/base/new_dropdowns/base_dropdown/base_dropdown.spec.js +36 -16
- package/src/components/base/new_dropdowns/base_dropdown/base_dropdown.vue +29 -3
- package/src/components/base/new_dropdowns/constants.js +1 -0
- package/src/components/base/new_dropdowns/disclosure/disclosure_dropdown.spec.js +14 -5
- package/src/components/base/new_dropdowns/disclosure/disclosure_dropdown.vue +3 -6
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
## [58.2.1](https://gitlab.com/gitlab-org/gitlab-ui/compare/v58.2.0...v58.2.1) (2023-03-21)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* **GlDisclosureDropdown:** Keep focus on toggle on open ([8dd3172](https://gitlab.com/gitlab-org/gitlab-ui/commit/8dd3172aaf304bad3b7a606dc6732af6a7390acf))
|
|
7
|
+
|
|
1
8
|
# [58.2.0](https://gitlab.com/gitlab-org/gitlab-ui/compare/v58.1.0...v58.2.0) (2023-03-17)
|
|
2
9
|
|
|
3
10
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import uniqueId from 'lodash/uniqueId';
|
|
2
2
|
import { createPopper } from '@popperjs/core';
|
|
3
3
|
import { buttonCategoryOptions, dropdownVariantOptions, buttonSizeOptions, dropdownPlacements } from '../../../../utils/constants';
|
|
4
|
-
import { POPPER_CONFIG, GL_DROPDOWN_SHOWN, GL_DROPDOWN_HIDDEN, ENTER, SPACE } from '../constants';
|
|
4
|
+
import { POPPER_CONFIG, GL_DROPDOWN_SHOWN, GL_DROPDOWN_HIDDEN, ENTER, SPACE, ARROW_DOWN, GL_DROPDOWN_FOCUS_CONTENT } from '../constants';
|
|
5
5
|
import { isElementFocusable, isElementTabbable, logWarning } from '../../../../utils/utils';
|
|
6
6
|
import GlButton from '../../button/button';
|
|
7
7
|
import GlIcon from '../../icon/icon';
|
|
@@ -156,6 +156,7 @@ var script = {
|
|
|
156
156
|
class: this.toggleButtonClasses,
|
|
157
157
|
...this.ariaAttributes,
|
|
158
158
|
listeners: {
|
|
159
|
+
keydown: event => this.onKeydown(event),
|
|
159
160
|
click: () => this.toggle()
|
|
160
161
|
}
|
|
161
162
|
};
|
|
@@ -253,11 +254,25 @@ var script = {
|
|
|
253
254
|
},
|
|
254
255
|
onKeydown(event) {
|
|
255
256
|
const {
|
|
256
|
-
code
|
|
257
|
+
code,
|
|
258
|
+
target: {
|
|
259
|
+
tagName
|
|
260
|
+
}
|
|
257
261
|
} = event;
|
|
258
|
-
|
|
262
|
+
let toggleOnEnter = true;
|
|
263
|
+
let toggleOnSpace = true;
|
|
264
|
+
if (tagName === 'BUTTON') {
|
|
265
|
+
toggleOnEnter = false;
|
|
266
|
+
toggleOnSpace = false;
|
|
267
|
+
} else if (tagName === 'A') {
|
|
268
|
+
toggleOnEnter = false;
|
|
269
|
+
}
|
|
270
|
+
if (code === ENTER && toggleOnEnter || code === SPACE && toggleOnSpace) {
|
|
259
271
|
this.toggle();
|
|
260
272
|
}
|
|
273
|
+
if (code === ARROW_DOWN) {
|
|
274
|
+
this.$emit(GL_DROPDOWN_FOCUS_CONTENT, event);
|
|
275
|
+
}
|
|
261
276
|
}
|
|
262
277
|
}
|
|
263
278
|
};
|
|
@@ -10,6 +10,7 @@ const POPPER_CONFIG = {
|
|
|
10
10
|
// base dropdown events
|
|
11
11
|
const GL_DROPDOWN_SHOWN = 'shown';
|
|
12
12
|
const GL_DROPDOWN_HIDDEN = 'hidden';
|
|
13
|
+
const GL_DROPDOWN_FOCUS_CONTENT = 'focusContent';
|
|
13
14
|
|
|
14
15
|
// KEY Codes
|
|
15
16
|
const ARROW_DOWN = 'ArrowDown';
|
|
@@ -19,4 +20,4 @@ const ENTER = 'Enter';
|
|
|
19
20
|
const HOME = 'Home';
|
|
20
21
|
const SPACE = 'Space';
|
|
21
22
|
|
|
22
|
-
export { ARROW_DOWN, ARROW_UP, END, ENTER, GL_DROPDOWN_HIDDEN, GL_DROPDOWN_SHOWN, HOME, POPPER_CONFIG, SPACE };
|
|
23
|
+
export { ARROW_DOWN, ARROW_UP, END, ENTER, GL_DROPDOWN_FOCUS_CONTENT, GL_DROPDOWN_HIDDEN, GL_DROPDOWN_SHOWN, HOME, POPPER_CONFIG, SPACE };
|
|
@@ -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, 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 } 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';
|
|
@@ -13,7 +13,8 @@ import __vue_normalize__ from 'vue-runtime-helpers/dist/normalize-component.js';
|
|
|
13
13
|
var script = {
|
|
14
14
|
events: {
|
|
15
15
|
GL_DROPDOWN_SHOWN,
|
|
16
|
-
GL_DROPDOWN_HIDDEN
|
|
16
|
+
GL_DROPDOWN_HIDDEN,
|
|
17
|
+
GL_DROPDOWN_FOCUS_CONTENT
|
|
17
18
|
},
|
|
18
19
|
components: {
|
|
19
20
|
GlBaseDropdown,
|
|
@@ -177,11 +178,6 @@ var script = {
|
|
|
177
178
|
this.$refs.baseDropdown.close();
|
|
178
179
|
},
|
|
179
180
|
onShow() {
|
|
180
|
-
const items = this.getFocusableListItemElements();
|
|
181
|
-
if (items.length) {
|
|
182
|
-
this.focusItem(0, items);
|
|
183
|
-
}
|
|
184
|
-
|
|
185
181
|
/**
|
|
186
182
|
* Emitted when dropdown is shown
|
|
187
183
|
*
|
|
@@ -257,7 +253,7 @@ var script = {
|
|
|
257
253
|
const __vue_script__ = script;
|
|
258
254
|
|
|
259
255
|
/* template */
|
|
260
|
-
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},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._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:item.text,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:groupItem.text,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)};
|
|
256
|
+
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},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:item.text,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:groupItem.text,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)};
|
|
261
257
|
var __vue_staticRenderFns__ = [];
|
|
262
258
|
|
|
263
259
|
/* style */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gitlab/ui",
|
|
3
|
-
"version": "58.2.
|
|
3
|
+
"version": "58.2.1",
|
|
4
4
|
"description": "GitLab UI Components",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -83,12 +83,12 @@
|
|
|
83
83
|
},
|
|
84
84
|
"devDependencies": {
|
|
85
85
|
"@arkweid/lefthook": "0.7.7",
|
|
86
|
-
"@babel/core": "^7.21.
|
|
86
|
+
"@babel/core": "^7.21.3",
|
|
87
87
|
"@babel/preset-env": "^7.20.2",
|
|
88
88
|
"@gitlab/eslint-plugin": "18.2.0",
|
|
89
89
|
"@gitlab/fonts": "^1.2.0",
|
|
90
90
|
"@gitlab/stylelint-config": "4.1.0",
|
|
91
|
-
"@gitlab/svgs": "3.
|
|
91
|
+
"@gitlab/svgs": "3.26.0",
|
|
92
92
|
"@rollup/plugin-commonjs": "^11.1.0",
|
|
93
93
|
"@rollup/plugin-node-resolve": "^7.1.3",
|
|
94
94
|
"@rollup/plugin-replace": "^2.3.2",
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import { mount } from '@vue/test-utils';
|
|
2
2
|
import { nextTick } from 'vue';
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
ARROW_DOWN,
|
|
5
|
+
GL_DROPDOWN_FOCUS_CONTENT,
|
|
6
|
+
GL_DROPDOWN_HIDDEN,
|
|
7
|
+
GL_DROPDOWN_SHOWN,
|
|
8
|
+
POPPER_CONFIG,
|
|
9
|
+
} from '../constants';
|
|
4
10
|
import GlBaseDropdown from './base_dropdown.vue';
|
|
5
11
|
|
|
6
12
|
const destroyPopper = jest.fn();
|
|
@@ -157,42 +163,50 @@ describe('base dropdown', () => {
|
|
|
157
163
|
});
|
|
158
164
|
});
|
|
159
165
|
|
|
160
|
-
describe('toggle
|
|
166
|
+
describe('default toggle', () => {
|
|
161
167
|
beforeEach(() => {
|
|
162
168
|
buildWrapper();
|
|
163
169
|
});
|
|
164
170
|
|
|
165
|
-
it('should
|
|
171
|
+
it('should open the menu on click but keep focus on toggle', async () => {
|
|
166
172
|
const toggle = findDefaultDropdownToggle();
|
|
167
173
|
const menu = findDropdownMenu();
|
|
168
174
|
|
|
175
|
+
toggle.element.focus();
|
|
169
176
|
// open menu clicking toggle btn
|
|
170
177
|
await toggle.trigger('click');
|
|
171
178
|
expect(menu.classes('gl-display-block!')).toBe(true);
|
|
172
179
|
expect(toggle.attributes('aria-expanded')).toBe('true');
|
|
173
|
-
|
|
174
|
-
expect(wrapper.emitted(GL_DROPDOWN_SHOWN).length).toBe(1);
|
|
180
|
+
expect(toggle.element).toHaveFocus();
|
|
175
181
|
|
|
176
|
-
// close menu clicking toggle btn
|
|
182
|
+
// close menu clicking toggle btn
|
|
177
183
|
await toggle.trigger('click');
|
|
178
184
|
expect(menu.classes('gl-display-block!')).toBe(false);
|
|
179
185
|
expect(toggle.attributes('aria-expanded')).toBeUndefined();
|
|
180
|
-
expect(wrapper.emitted(GL_DROPDOWN_HIDDEN)
|
|
186
|
+
expect(wrapper.emitted(GL_DROPDOWN_HIDDEN)).toHaveLength(1);
|
|
187
|
+
expect(toggle.element).toHaveFocus();
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
it('should emit `GL_DROPDOWN_FOCUS_CONTENT` event on `ARROW_DOWN`', () => {
|
|
191
|
+
findDefaultDropdownToggle().trigger('keydown', { code: ARROW_DOWN });
|
|
192
|
+
expect(wrapper.emitted(GL_DROPDOWN_FOCUS_CONTENT)).toHaveLength(1);
|
|
181
193
|
});
|
|
182
194
|
|
|
183
|
-
it('should close
|
|
195
|
+
it('should close menu on Escape and focus toggle', async () => {
|
|
184
196
|
const toggle = findDefaultDropdownToggle();
|
|
185
197
|
const menu = findDropdownMenu();
|
|
186
198
|
|
|
187
199
|
// open menu clicking toggle btn
|
|
188
200
|
await toggle.trigger('click');
|
|
189
201
|
expect(menu.classes('gl-display-block!')).toBe(true);
|
|
202
|
+
expect(toggle.attributes('aria-expanded')).toBe('true');
|
|
190
203
|
|
|
191
|
-
// close menu
|
|
204
|
+
// close menu clicking toggle btn
|
|
205
|
+
menu.element.focus();
|
|
192
206
|
await menu.trigger('keydown.esc');
|
|
193
207
|
expect(menu.classes('gl-display-block!')).toBe(false);
|
|
194
208
|
expect(toggle.attributes('aria-expanded')).toBeUndefined();
|
|
195
|
-
expect(wrapper.emitted(GL_DROPDOWN_HIDDEN)
|
|
209
|
+
expect(wrapper.emitted(GL_DROPDOWN_HIDDEN)).toHaveLength(1);
|
|
196
210
|
expect(toggle.element).toHaveFocus();
|
|
197
211
|
});
|
|
198
212
|
});
|
|
@@ -221,22 +235,22 @@ describe('base dropdown', () => {
|
|
|
221
235
|
});
|
|
222
236
|
|
|
223
237
|
describe('toggle visibility', () => {
|
|
224
|
-
it('should toggle menu visibility on toggle
|
|
238
|
+
it('should toggle menu visibility on toggle click', async () => {
|
|
225
239
|
const toggle = findCustomDropdownToggle();
|
|
226
240
|
const firstToggleChild = findFirstToggleElement();
|
|
227
241
|
const menu = findDropdownMenu();
|
|
228
242
|
// open menu clicking toggle btn
|
|
229
|
-
await toggle.trigger('
|
|
243
|
+
await toggle.trigger('click');
|
|
230
244
|
expect(menu.classes('gl-display-block!')).toBe(true);
|
|
231
245
|
expect(firstToggleChild.attributes('aria-expanded')).toBe('true');
|
|
232
246
|
await nextTick();
|
|
233
|
-
expect(wrapper.emitted(GL_DROPDOWN_SHOWN)
|
|
247
|
+
expect(wrapper.emitted(GL_DROPDOWN_SHOWN)).toHaveLength(1);
|
|
234
248
|
|
|
235
249
|
// close menu clicking toggle btn again
|
|
236
|
-
await toggle.trigger('
|
|
250
|
+
await toggle.trigger('click');
|
|
237
251
|
expect(menu.classes('gl-display-block!')).toBe(false);
|
|
238
252
|
expect(firstToggleChild.attributes('aria-expanded')).toBe('false');
|
|
239
|
-
expect(wrapper.emitted(GL_DROPDOWN_HIDDEN)
|
|
253
|
+
expect(wrapper.emitted(GL_DROPDOWN_HIDDEN)).toHaveLength(1);
|
|
240
254
|
});
|
|
241
255
|
|
|
242
256
|
it('should close the menu when Escape is pressed inside menu and focus first child in the toggle', async () => {
|
|
@@ -251,9 +265,15 @@ describe('base dropdown', () => {
|
|
|
251
265
|
await menu.trigger('keydown.esc');
|
|
252
266
|
expect(menu.classes('gl-display-block!')).toBe(false);
|
|
253
267
|
expect(firstToggleChild.attributes('aria-expanded')).toBe('false');
|
|
254
|
-
expect(wrapper.emitted(GL_DROPDOWN_HIDDEN)
|
|
268
|
+
expect(wrapper.emitted(GL_DROPDOWN_HIDDEN)).toHaveLength(1);
|
|
255
269
|
expect(toggle.find(`[data-testid="${customToggleTestId}"]`).element).toHaveFocus();
|
|
256
270
|
});
|
|
257
271
|
});
|
|
272
|
+
|
|
273
|
+
it('should emit `GL_DROPDOWN_FOCUS_CONTENT` event on `ARROW_DOWN`', () => {
|
|
274
|
+
const toggle = findCustomDropdownToggle();
|
|
275
|
+
toggle.trigger('keydown', { code: ARROW_DOWN });
|
|
276
|
+
expect(wrapper.emitted(GL_DROPDOWN_FOCUS_CONTENT)).toHaveLength(1);
|
|
277
|
+
});
|
|
258
278
|
});
|
|
259
279
|
});
|
|
@@ -7,7 +7,15 @@ import {
|
|
|
7
7
|
dropdownPlacements,
|
|
8
8
|
dropdownVariantOptions,
|
|
9
9
|
} from '../../../../utils/constants';
|
|
10
|
-
import {
|
|
10
|
+
import {
|
|
11
|
+
POPPER_CONFIG,
|
|
12
|
+
GL_DROPDOWN_SHOWN,
|
|
13
|
+
GL_DROPDOWN_HIDDEN,
|
|
14
|
+
GL_DROPDOWN_FOCUS_CONTENT,
|
|
15
|
+
ENTER,
|
|
16
|
+
SPACE,
|
|
17
|
+
ARROW_DOWN,
|
|
18
|
+
} from '../constants';
|
|
11
19
|
import { logWarning, isElementTabbable, isElementFocusable } from '../../../../utils/utils';
|
|
12
20
|
|
|
13
21
|
import GlButton from '../../button/button.vue';
|
|
@@ -162,6 +170,7 @@ export default {
|
|
|
162
170
|
class: this.toggleButtonClasses,
|
|
163
171
|
...this.ariaAttributes,
|
|
164
172
|
listeners: {
|
|
173
|
+
keydown: (event) => this.onKeydown(event),
|
|
165
174
|
click: () => this.toggle(),
|
|
166
175
|
},
|
|
167
176
|
};
|
|
@@ -260,11 +269,28 @@ export default {
|
|
|
260
269
|
this.toggleElement.focus();
|
|
261
270
|
},
|
|
262
271
|
onKeydown(event) {
|
|
263
|
-
const {
|
|
272
|
+
const {
|
|
273
|
+
code,
|
|
274
|
+
target: { tagName },
|
|
275
|
+
} = event;
|
|
276
|
+
|
|
277
|
+
let toggleOnEnter = true;
|
|
278
|
+
let toggleOnSpace = true;
|
|
279
|
+
|
|
280
|
+
if (tagName === 'BUTTON') {
|
|
281
|
+
toggleOnEnter = false;
|
|
282
|
+
toggleOnSpace = false;
|
|
283
|
+
} else if (tagName === 'A') {
|
|
284
|
+
toggleOnEnter = false;
|
|
285
|
+
}
|
|
264
286
|
|
|
265
|
-
if (code === ENTER || code === SPACE) {
|
|
287
|
+
if ((code === ENTER && toggleOnEnter) || (code === SPACE && toggleOnSpace)) {
|
|
266
288
|
this.toggle();
|
|
267
289
|
}
|
|
290
|
+
|
|
291
|
+
if (code === ARROW_DOWN) {
|
|
292
|
+
this.$emit(GL_DROPDOWN_FOCUS_CONTENT, event);
|
|
293
|
+
}
|
|
268
294
|
},
|
|
269
295
|
},
|
|
270
296
|
};
|
|
@@ -12,6 +12,7 @@ export const POPPER_CONFIG = {
|
|
|
12
12
|
// base dropdown events
|
|
13
13
|
export const GL_DROPDOWN_SHOWN = 'shown';
|
|
14
14
|
export const GL_DROPDOWN_HIDDEN = 'hidden';
|
|
15
|
+
export const GL_DROPDOWN_FOCUS_CONTENT = 'focusContent';
|
|
15
16
|
|
|
16
17
|
// KEY Codes
|
|
17
18
|
export const ARROW_DOWN = 'ArrowDown';
|
|
@@ -4,6 +4,7 @@ import GlBaseDropdown from '../base_dropdown/base_dropdown.vue';
|
|
|
4
4
|
import {
|
|
5
5
|
GL_DROPDOWN_SHOWN,
|
|
6
6
|
GL_DROPDOWN_HIDDEN,
|
|
7
|
+
GL_DROPDOWN_FOCUS_CONTENT,
|
|
7
8
|
ARROW_DOWN,
|
|
8
9
|
ARROW_UP,
|
|
9
10
|
HOME,
|
|
@@ -82,10 +83,6 @@ describe('GlDisclosureDropdown', () => {
|
|
|
82
83
|
it('should re-emit the event', () => {
|
|
83
84
|
expect(wrapper.emitted(GL_DROPDOWN_SHOWN)).toHaveLength(1);
|
|
84
85
|
});
|
|
85
|
-
|
|
86
|
-
it('should focus the first item', () => {
|
|
87
|
-
expect(findDisclosureItems().at(0).find(ITEM_SELECTOR).element).toHaveFocus();
|
|
88
|
-
});
|
|
89
86
|
});
|
|
90
87
|
|
|
91
88
|
describe('onHide', () => {
|
|
@@ -112,7 +109,11 @@ describe('GlDisclosureDropdown', () => {
|
|
|
112
109
|
thirdItem = findListItem(2);
|
|
113
110
|
});
|
|
114
111
|
|
|
115
|
-
it('should move the focus down the list of items on `ARROW_DOWN` and stop on the last item', async () => {
|
|
112
|
+
it('should move the focus from toggle and down the list of items on `ARROW_DOWN` and stop on the last item', async () => {
|
|
113
|
+
findBaseDropdown().vm.$emit(
|
|
114
|
+
GL_DROPDOWN_FOCUS_CONTENT,
|
|
115
|
+
new KeyboardEvent('keydown', { code: ARROW_DOWN })
|
|
116
|
+
);
|
|
116
117
|
expect(firstItem.element).toHaveFocus();
|
|
117
118
|
await firstItem.trigger('keydown', { code: ARROW_DOWN });
|
|
118
119
|
expect(secondItem.element).toHaveFocus();
|
|
@@ -135,6 +136,10 @@ describe('GlDisclosureDropdown', () => {
|
|
|
135
136
|
});
|
|
136
137
|
|
|
137
138
|
it('should move focus to the last item on `END` keydown', async () => {
|
|
139
|
+
findBaseDropdown().vm.$emit(
|
|
140
|
+
GL_DROPDOWN_FOCUS_CONTENT,
|
|
141
|
+
new KeyboardEvent('keydown', { code: ARROW_DOWN })
|
|
142
|
+
);
|
|
138
143
|
expect(firstItem.element).toHaveFocus();
|
|
139
144
|
await firstItem.trigger('keydown', { code: END });
|
|
140
145
|
expect(thirdItem.element).toHaveFocus();
|
|
@@ -158,6 +163,10 @@ describe('GlDisclosureDropdown', () => {
|
|
|
158
163
|
});
|
|
159
164
|
|
|
160
165
|
it('should skip over it', async () => {
|
|
166
|
+
findBaseDropdown().vm.$emit(
|
|
167
|
+
GL_DROPDOWN_FOCUS_CONTENT,
|
|
168
|
+
new KeyboardEvent('keydown', { code: ARROW_DOWN })
|
|
169
|
+
);
|
|
161
170
|
expect(firstItem.element).toHaveFocus();
|
|
162
171
|
await firstItem.trigger('keydown', { code: ARROW_DOWN });
|
|
163
172
|
|
|
@@ -6,6 +6,7 @@ import { stopEvent, filterVisible } from '../../../../utils/utils';
|
|
|
6
6
|
import {
|
|
7
7
|
GL_DROPDOWN_SHOWN,
|
|
8
8
|
GL_DROPDOWN_HIDDEN,
|
|
9
|
+
GL_DROPDOWN_FOCUS_CONTENT,
|
|
9
10
|
HOME,
|
|
10
11
|
END,
|
|
11
12
|
ARROW_DOWN,
|
|
@@ -26,6 +27,7 @@ export default {
|
|
|
26
27
|
events: {
|
|
27
28
|
GL_DROPDOWN_SHOWN,
|
|
28
29
|
GL_DROPDOWN_HIDDEN,
|
|
30
|
+
GL_DROPDOWN_FOCUS_CONTENT,
|
|
29
31
|
},
|
|
30
32
|
components: {
|
|
31
33
|
GlBaseDropdown,
|
|
@@ -188,12 +190,6 @@ export default {
|
|
|
188
190
|
this.$refs.baseDropdown.close();
|
|
189
191
|
},
|
|
190
192
|
onShow() {
|
|
191
|
-
const items = this.getFocusableListItemElements();
|
|
192
|
-
|
|
193
|
-
if (items.length) {
|
|
194
|
-
this.focusItem(0, items);
|
|
195
|
-
}
|
|
196
|
-
|
|
197
193
|
/**
|
|
198
194
|
* Emitted when dropdown is shown
|
|
199
195
|
*
|
|
@@ -285,6 +281,7 @@ export default {
|
|
|
285
281
|
class="gl-disclosure-dropdown"
|
|
286
282
|
@[$options.events.GL_DROPDOWN_SHOWN]="onShow"
|
|
287
283
|
@[$options.events.GL_DROPDOWN_HIDDEN]="onHide"
|
|
284
|
+
@[$options.events.GL_DROPDOWN_FOCUS_CONTENT]="onKeydown"
|
|
288
285
|
>
|
|
289
286
|
<template v-if="hasCustomToggle" #toggle>
|
|
290
287
|
<!-- @slot Custom toggle content -->
|