@gitlab/ui 72.8.0 → 72.8.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/form/form_checkbox_tree/checkbox_tree_node.js +1 -1
- package/dist/components/base/new_dropdowns/base_dropdown/base_dropdown.js +9 -0
- package/dist/components/base/token_selector/token_selector.js +1 -1
- package/dist/tokens/css/tokens.css +1 -1
- package/dist/tokens/css/tokens.dark.css +1 -1
- package/dist/tokens/js/tokens.dark.js +1 -1
- package/dist/tokens/js/tokens.js +1 -1
- package/dist/tokens/scss/_tokens.dark.scss +1 -1
- package/dist/tokens/scss/_tokens.scss +1 -1
- package/package.json +1 -1
- package/src/components/base/filtered_search/filtered_search.spec.js +2 -2
- package/src/components/base/filtered_search/filtered_search_term.spec.js +2 -4
- package/src/components/base/filtered_search/filtered_search_token_segment.spec.js +5 -7
- package/src/components/base/form/form_checkbox_tree/checkbox_tree_node.vue +1 -1
- package/src/components/base/form/form_checkbox_tree/form_checkbox_tree.spec.js +2 -2
- package/src/components/base/new_dropdowns/base_dropdown/base_dropdown.spec.js +41 -4
- package/src/components/base/new_dropdowns/base_dropdown/base_dropdown.vue +12 -0
- package/src/components/base/search_box_by_click/search_box_by_click.spec.js +2 -4
- package/src/components/base/token_selector/token_selector.spec.js +2 -2
- package/src/components/base/token_selector/token_selector.vue +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
## [72.8.1](https://gitlab.com/gitlab-org/gitlab-ui/compare/v72.8.0...v72.8.1) (2024-01-18)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* **dropdowns:** do not steal focus back from the consumer ([69295fa](https://gitlab.com/gitlab-org/gitlab-ui/commit/69295faa28dfe48b90e75ab86c9d3ba615760c96))
|
|
7
|
+
|
|
1
8
|
# [72.8.0](https://gitlab.com/gitlab-org/gitlab-ui/compare/v72.7.0...v72.8.0) (2024-01-16)
|
|
2
9
|
|
|
3
10
|
|
|
@@ -44,7 +44,7 @@ var script = {
|
|
|
44
44
|
const __vue_script__ = script;
|
|
45
45
|
|
|
46
46
|
/* template */
|
|
47
|
-
var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{class:_vm.rootClass,attrs:{"data-
|
|
47
|
+
var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{class:_vm.rootClass,attrs:{"data-testid":("" + (_vm.$options.qaPrefix) + (_vm.option.value))}},[_c('gl-form-checkbox',{class:_vm.checkboxClass,attrs:{"checked":_vm.node.isChecked,"indeterminate":_vm.node.isIndeterminate},on:{"change":function($event){return _vm.tree.toggleOption(_vm.option, $event)}}},[_vm._v("\n "+_vm._s(_vm.label)+"\n ")]),_vm._v(" "),_vm._l((_vm.option.children),function(child){return _c('gl-form-checkbox-tree-node',{key:child.value,attrs:{"option":child,"is-nested":""}})})],2)};
|
|
48
48
|
var __vue_staticRenderFns__ = [];
|
|
49
49
|
|
|
50
50
|
/* style */
|
|
@@ -359,11 +359,20 @@ var script = {
|
|
|
359
359
|
}
|
|
360
360
|
this.toggle(event);
|
|
361
361
|
},
|
|
362
|
+
/**
|
|
363
|
+
* Closes the dropdown and returns the focus to the toggle unless it has has moved outside
|
|
364
|
+
* of the dropdown, meaning that the consumer needed to put some other element in focus.
|
|
365
|
+
*
|
|
366
|
+
* @param {KeyboardEvent?} event The keyboard event that caused the dropdown to close.
|
|
367
|
+
*/
|
|
362
368
|
async closeAndFocus(event) {
|
|
363
369
|
if (!this.visible) {
|
|
364
370
|
return;
|
|
365
371
|
}
|
|
366
372
|
const hasToggled = await this.toggle(event);
|
|
373
|
+
if (!this.$el.contains(document.activeElement)) {
|
|
374
|
+
return;
|
|
375
|
+
}
|
|
367
376
|
if (hasToggled) {
|
|
368
377
|
this.focusToggle();
|
|
369
378
|
}
|
|
@@ -91,7 +91,7 @@ var script = {
|
|
|
91
91
|
default: null
|
|
92
92
|
},
|
|
93
93
|
/**
|
|
94
|
-
* HTML attributes to add to the text input. Helpful for adding `data-testid`
|
|
94
|
+
* HTML attributes to add to the text input. Helpful for adding `data-testid` attributes
|
|
95
95
|
*/
|
|
96
96
|
textInputAttrs: {
|
|
97
97
|
type: Object,
|
package/dist/tokens/js/tokens.js
CHANGED
package/package.json
CHANGED
|
@@ -476,7 +476,7 @@ describe('Filtered search', () => {
|
|
|
476
476
|
});
|
|
477
477
|
|
|
478
478
|
it('passes `searchButtonAttributes` prop to `GlSearchBoxByClick`', () => {
|
|
479
|
-
const searchButtonAttributes = { 'data-
|
|
479
|
+
const searchButtonAttributes = { 'data-prop': 'foo-bar' };
|
|
480
480
|
|
|
481
481
|
createComponent({ searchButtonAttributes });
|
|
482
482
|
|
|
@@ -484,7 +484,7 @@ describe('Filtered search', () => {
|
|
|
484
484
|
});
|
|
485
485
|
|
|
486
486
|
it('passes `searchInputAttributes` prop to search term', async () => {
|
|
487
|
-
const searchInputAttributes = { 'data-
|
|
487
|
+
const searchInputAttributes = { 'data-prop': 'foo-bar' };
|
|
488
488
|
|
|
489
489
|
createComponent({
|
|
490
490
|
value: ['one'],
|
|
@@ -15,7 +15,7 @@ const pointerClass = 'gl-cursor-pointer';
|
|
|
15
15
|
describe('Filtered search term', () => {
|
|
16
16
|
let wrapper;
|
|
17
17
|
|
|
18
|
-
const searchInputAttributes = { 'data-
|
|
18
|
+
const searchInputAttributes = { 'data-testid': 'foo-bar', 'data-prop': 'foo-property' };
|
|
19
19
|
|
|
20
20
|
const defaultProps = {
|
|
21
21
|
availableTokens: [],
|
|
@@ -182,9 +182,7 @@ describe('Filtered search term', () => {
|
|
|
182
182
|
searchInputAttributes,
|
|
183
183
|
});
|
|
184
184
|
|
|
185
|
-
expect(findSearchInput().attributes('data-
|
|
186
|
-
searchInputAttributes['data-qa-selector']
|
|
187
|
-
);
|
|
185
|
+
expect(findSearchInput().attributes('data-prop')).toBe(searchInputAttributes['data-prop']);
|
|
188
186
|
});
|
|
189
187
|
|
|
190
188
|
it('activates and deactivates when the input is focused/blurred', async () => {
|
|
@@ -10,7 +10,7 @@ const OPTIONS = [
|
|
|
10
10
|
describe('Filtered search token segment', () => {
|
|
11
11
|
let wrapper;
|
|
12
12
|
|
|
13
|
-
const searchInputAttributes = { 'data-
|
|
13
|
+
const searchInputAttributes = { 'data-prop': 'foo-bar' };
|
|
14
14
|
|
|
15
15
|
beforeAll(() => {
|
|
16
16
|
if (!HTMLElement.prototype.scrollIntoView) {
|
|
@@ -336,7 +336,7 @@ describe('Filtered search token segment', () => {
|
|
|
336
336
|
});
|
|
337
337
|
|
|
338
338
|
it('does not add `searchInputAttributes` prop to search token segment', () => {
|
|
339
|
-
expect(wrapper.attributes('data-
|
|
339
|
+
expect(wrapper.attributes('data-prop')).toBe(undefined);
|
|
340
340
|
});
|
|
341
341
|
}
|
|
342
342
|
);
|
|
@@ -353,9 +353,7 @@ describe('Filtered search token segment', () => {
|
|
|
353
353
|
});
|
|
354
354
|
|
|
355
355
|
it('adds `searchInputAttributes` prop to search token segment', () => {
|
|
356
|
-
expect(wrapper.attributes('data-
|
|
357
|
-
searchInputAttributes['data-qa-selector']
|
|
358
|
-
);
|
|
356
|
+
expect(wrapper.attributes('data-prop')).toBe(searchInputAttributes['data-prop']);
|
|
359
357
|
});
|
|
360
358
|
});
|
|
361
359
|
|
|
@@ -363,8 +361,8 @@ describe('Filtered search token segment', () => {
|
|
|
363
361
|
it('adds `searchInputAttributes` prop to search token segment input', () => {
|
|
364
362
|
createComponent({ active: true, value: 'something', searchInputAttributes });
|
|
365
363
|
|
|
366
|
-
expect(wrapper.find('input').attributes('data-
|
|
367
|
-
searchInputAttributes['data-
|
|
364
|
+
expect(wrapper.find('input').attributes('data-prop')).toBe(
|
|
365
|
+
searchInputAttributes['data-prop']
|
|
368
366
|
);
|
|
369
367
|
});
|
|
370
368
|
|
|
@@ -39,7 +39,7 @@ export default {
|
|
|
39
39
|
</script>
|
|
40
40
|
|
|
41
41
|
<template>
|
|
42
|
-
<div :class="rootClass" :data-
|
|
42
|
+
<div :class="rootClass" :data-testid="`${$options.qaPrefix}${option.value}`">
|
|
43
43
|
<gl-form-checkbox
|
|
44
44
|
:checked="node.isChecked"
|
|
45
45
|
:indeterminate="node.isIndeterminate"
|
|
@@ -87,7 +87,7 @@ describe('GlFormCheckboxTree', () => {
|
|
|
87
87
|
const findCheckboxes = (el = wrapper) => el.findAllComponents(GlFormCheckbox);
|
|
88
88
|
const countIndeterminate = () => wrapper.findAll('.js-is-indeterminate').length || 0;
|
|
89
89
|
const countChecked = () => wrapper.findAll('.js-is-checked').length || 0;
|
|
90
|
-
const findCheckboxByValue = (value) => wrapper.find(`[data-
|
|
90
|
+
const findCheckboxByValue = (value) => wrapper.find(`[data-testid="${QA_PREFIX}${value}"]`);
|
|
91
91
|
const getCheckboxesCount = (el) => findCheckboxes(el).length;
|
|
92
92
|
const findCheckboxInput = (checkbox) => checkbox.find('input[type="checkbox"]');
|
|
93
93
|
const expectCheckboxUnchecked = (checkbox) => {
|
|
@@ -152,7 +152,7 @@ describe('GlFormCheckboxTree', () => {
|
|
|
152
152
|
|
|
153
153
|
beforeEach(async () => {
|
|
154
154
|
createWrapper({ options: getOptions(shape) });
|
|
155
|
-
checkbox = wrapper.find(`[data-
|
|
155
|
+
checkbox = wrapper.find(`[data-testid="${QA_PREFIX}${boxToCheck}"]`);
|
|
156
156
|
await checkbox.find('input').setChecked();
|
|
157
157
|
});
|
|
158
158
|
|
|
@@ -36,7 +36,7 @@ describe('base dropdown', () => {
|
|
|
36
36
|
...propsData,
|
|
37
37
|
},
|
|
38
38
|
slots: {
|
|
39
|
-
default: `<div class="${GL_DROPDOWN_CONTENTS_CLASS}"
|
|
39
|
+
default: `<div class="${GL_DROPDOWN_CONTENTS_CLASS}"><button /></div>`,
|
|
40
40
|
...slots,
|
|
41
41
|
},
|
|
42
42
|
attachTo: document.body,
|
|
@@ -57,6 +57,8 @@ describe('base dropdown', () => {
|
|
|
57
57
|
const findDropdownToggleText = () => findDefaultDropdownToggle().find('.gl-button-text');
|
|
58
58
|
const findDropdownMenu = () => wrapper.find('.gl-new-dropdown-panel');
|
|
59
59
|
|
|
60
|
+
const moveFocusWithinDropdown = () => findDropdownMenu().find('button').element.focus();
|
|
61
|
+
|
|
60
62
|
describe('Floating UI instance', () => {
|
|
61
63
|
it("starts Floating UI's when opening the dropdown", async () => {
|
|
62
64
|
buildWrapper();
|
|
@@ -324,14 +326,47 @@ describe('base dropdown', () => {
|
|
|
324
326
|
expect(menu.classes('gl-display-block!')).toBe(true);
|
|
325
327
|
expect(toggle.attributes('aria-expanded')).toBe('true');
|
|
326
328
|
|
|
327
|
-
|
|
328
|
-
|
|
329
|
+
moveFocusWithinDropdown();
|
|
330
|
+
|
|
331
|
+
// close menu by pressing ESC key
|
|
329
332
|
await menu.trigger('keydown.esc');
|
|
333
|
+
|
|
330
334
|
expect(menu.classes('gl-display-block!')).toBe(false);
|
|
331
335
|
expect(toggle.attributes('aria-expanded')).toBeUndefined();
|
|
332
336
|
expect(wrapper.emitted(GL_DROPDOWN_HIDDEN)).toHaveLength(1);
|
|
333
337
|
expect(toggle.element).toHaveFocus();
|
|
334
338
|
});
|
|
339
|
+
|
|
340
|
+
describe('when the consumer takes over the focus', () => {
|
|
341
|
+
let consumerButton;
|
|
342
|
+
|
|
343
|
+
beforeEach(() => {
|
|
344
|
+
consumerButton = document.createElement('button');
|
|
345
|
+
document.body.appendChild(consumerButton);
|
|
346
|
+
});
|
|
347
|
+
|
|
348
|
+
afterEach(() => {
|
|
349
|
+
consumerButton.remove();
|
|
350
|
+
});
|
|
351
|
+
|
|
352
|
+
it('does not steal the focus back from the consumer when closing the dropdown', async () => {
|
|
353
|
+
const toggle = findDefaultDropdownToggle();
|
|
354
|
+
const menu = findDropdownMenu();
|
|
355
|
+
|
|
356
|
+
// open menu clicking toggle btn
|
|
357
|
+
await toggle.trigger('click');
|
|
358
|
+
|
|
359
|
+
moveFocusWithinDropdown();
|
|
360
|
+
|
|
361
|
+
// consumer focuses some element
|
|
362
|
+
consumerButton.focus();
|
|
363
|
+
|
|
364
|
+
// close menu by pressing ESC key
|
|
365
|
+
await menu.trigger('keydown.esc');
|
|
366
|
+
|
|
367
|
+
expect(consumerButton).toHaveFocus();
|
|
368
|
+
});
|
|
369
|
+
});
|
|
335
370
|
});
|
|
336
371
|
|
|
337
372
|
describe('beforeClose event', () => {
|
|
@@ -353,7 +388,7 @@ describe('base dropdown', () => {
|
|
|
353
388
|
|
|
354
389
|
await toggle.trigger('click');
|
|
355
390
|
|
|
356
|
-
|
|
391
|
+
moveFocusWithinDropdown();
|
|
357
392
|
await menu.trigger('keydown.esc');
|
|
358
393
|
expect(menu.classes('gl-display-block!')).toBe(true);
|
|
359
394
|
expect(toggle.attributes('aria-expanded')).toBeDefined();
|
|
@@ -365,6 +400,7 @@ describe('base dropdown', () => {
|
|
|
365
400
|
const toggle = findDefaultDropdownToggle();
|
|
366
401
|
const menu = findDropdownMenu();
|
|
367
402
|
await toggle.trigger('click');
|
|
403
|
+
moveFocusWithinDropdown();
|
|
368
404
|
await menu.trigger('keydown.esc');
|
|
369
405
|
expect(event.type).toBe('keydown');
|
|
370
406
|
});
|
|
@@ -444,6 +480,7 @@ describe('base dropdown', () => {
|
|
|
444
480
|
expect(menu.classes('gl-display-block!')).toBe(true);
|
|
445
481
|
|
|
446
482
|
// close menu pressing ESC on it
|
|
483
|
+
moveFocusWithinDropdown();
|
|
447
484
|
await menu.trigger('keydown.esc');
|
|
448
485
|
expect(menu.classes('gl-display-block!')).toBe(false);
|
|
449
486
|
expect(firstToggleChild.attributes('aria-expanded')).toBe('false');
|
|
@@ -382,11 +382,23 @@ export default {
|
|
|
382
382
|
}
|
|
383
383
|
this.toggle(event);
|
|
384
384
|
},
|
|
385
|
+
/**
|
|
386
|
+
* Closes the dropdown and returns the focus to the toggle unless it has has moved outside
|
|
387
|
+
* of the dropdown, meaning that the consumer needed to put some other element in focus.
|
|
388
|
+
*
|
|
389
|
+
* @param {KeyboardEvent?} event The keyboard event that caused the dropdown to close.
|
|
390
|
+
*/
|
|
385
391
|
async closeAndFocus(event) {
|
|
386
392
|
if (!this.visible) {
|
|
387
393
|
return;
|
|
388
394
|
}
|
|
395
|
+
|
|
389
396
|
const hasToggled = await this.toggle(event);
|
|
397
|
+
|
|
398
|
+
if (!this.$el.contains(document.activeElement)) {
|
|
399
|
+
return;
|
|
400
|
+
}
|
|
401
|
+
|
|
390
402
|
if (hasToggled) {
|
|
391
403
|
this.focusToggle();
|
|
392
404
|
}
|
|
@@ -162,12 +162,10 @@ describe('search box by click component', () => {
|
|
|
162
162
|
});
|
|
163
163
|
|
|
164
164
|
it('adds `searchButtonAttributes` prop to search button', () => {
|
|
165
|
-
const searchButtonAttributes = { 'data-
|
|
165
|
+
const searchButtonAttributes = { 'data-prop': 'foo-bar' };
|
|
166
166
|
|
|
167
167
|
createComponent({ searchButtonAttributes });
|
|
168
168
|
|
|
169
|
-
expect(findSearchButton().attributes('data-
|
|
170
|
-
searchButtonAttributes['data-qa-selector']
|
|
171
|
-
);
|
|
169
|
+
expect(findSearchButton().attributes('data-prop')).toBe(searchButtonAttributes['data-prop']);
|
|
172
170
|
});
|
|
173
171
|
});
|
|
@@ -254,12 +254,12 @@ describe('GlTokenSelector', () => {
|
|
|
254
254
|
createComponent({
|
|
255
255
|
propsData: {
|
|
256
256
|
textInputAttrs: {
|
|
257
|
-
'data-
|
|
257
|
+
'data-prop': 'foo_bar',
|
|
258
258
|
},
|
|
259
259
|
},
|
|
260
260
|
});
|
|
261
261
|
|
|
262
|
-
expect(findTextInput().attributes('data-
|
|
262
|
+
expect(findTextInput().attributes('data-prop')).toBe('foo_bar');
|
|
263
263
|
});
|
|
264
264
|
});
|
|
265
265
|
|
|
@@ -91,7 +91,7 @@ export default {
|
|
|
91
91
|
default: null,
|
|
92
92
|
},
|
|
93
93
|
/**
|
|
94
|
-
* HTML attributes to add to the text input. Helpful for adding `data-testid`
|
|
94
|
+
* HTML attributes to add to the text input. Helpful for adding `data-testid` attributes
|
|
95
95
|
*/
|
|
96
96
|
textInputAttrs: {
|
|
97
97
|
type: Object,
|