@gitlab/ui 72.8.0 → 72.9.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/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/index.css +2 -2
- package/dist/index.css.map +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/dist/utility_classes.css +1 -1
- package/dist/utility_classes.css.map +1 -1
- package/package.json +10 -4
- 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/src/scss/storybook.scss +3 -0
- package/src/scss/utilities.scss +10 -0
- package/src/scss/utility-mixins/spacing.scss +6 -0
- package/tailwind.defaults.js +5 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gitlab/ui",
|
|
3
|
-
"version": "72.
|
|
3
|
+
"version": "72.9.0",
|
|
4
4
|
"description": "GitLab UI Components",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -17,13 +17,15 @@
|
|
|
17
17
|
"files": [
|
|
18
18
|
"src",
|
|
19
19
|
"dist",
|
|
20
|
-
"translations.json"
|
|
20
|
+
"translations.json",
|
|
21
|
+
"tailwind.defaults.js"
|
|
21
22
|
],
|
|
22
23
|
"scripts": {
|
|
23
24
|
"build": "NODE_ENV=production rollup -c",
|
|
24
25
|
"prebuild": "run-s build-tokens generate-utilities",
|
|
25
26
|
"prepare": "run-s build-tokens generate-utilities",
|
|
26
27
|
"generate-utilities": "make src/scss/utilities.scss",
|
|
28
|
+
"deprecate-gl-utils": "./bin/deprecate_utils.js",
|
|
27
29
|
"copy-fonts": "make copy-fonts",
|
|
28
30
|
"build-tokens": "node ./bin/build_tokens.js",
|
|
29
31
|
"clean": "rm -r dist storybook src/scss/utilities.scss",
|
|
@@ -61,7 +63,8 @@
|
|
|
61
63
|
"lint": "run-p prettier eslint stylelint markdownlint",
|
|
62
64
|
"lint:fix": "run-s prettier:fix eslint:fix stylelint:fix markdownlint:fix",
|
|
63
65
|
"generate:component": "plop",
|
|
64
|
-
"translations:collect": "make translations.json"
|
|
66
|
+
"translations:collect": "make translations.json",
|
|
67
|
+
"tailwind-config-viewer": "tailwind-config-viewer -o"
|
|
65
68
|
},
|
|
66
69
|
"dependencies": {
|
|
67
70
|
"@floating-ui/dom": "1.4.3",
|
|
@@ -78,6 +81,7 @@
|
|
|
78
81
|
"dompurify": "^2.4.7 || ^3.0.5",
|
|
79
82
|
"emoji-regex": ">=10.0.0",
|
|
80
83
|
"pikaday": "^1.8.0",
|
|
84
|
+
"tailwindcss": "3^",
|
|
81
85
|
"vue": "^2.7.16"
|
|
82
86
|
},
|
|
83
87
|
"resolutions": {
|
|
@@ -154,7 +158,7 @@
|
|
|
154
158
|
"react-dom": "^18.2.0",
|
|
155
159
|
"rollup": "^2.53.1",
|
|
156
160
|
"rollup-plugin-babel": "^4.4.0",
|
|
157
|
-
"rollup-plugin-postcss": "
|
|
161
|
+
"rollup-plugin-postcss": "4.0.2",
|
|
158
162
|
"rollup-plugin-string": "^3.0.0",
|
|
159
163
|
"rollup-plugin-svg": "^2.0.0",
|
|
160
164
|
"rollup-plugin-vue": "^5.1.6",
|
|
@@ -167,6 +171,8 @@
|
|
|
167
171
|
"storybook-dark-mode": "3.0.3",
|
|
168
172
|
"style-dictionary": "^3.8.0",
|
|
169
173
|
"stylelint": "15.10.2",
|
|
174
|
+
"tailwind-config-viewer": "1.7.3",
|
|
175
|
+
"tailwindcss": "3.4.1",
|
|
170
176
|
"vue": "2.7.16",
|
|
171
177
|
"vue-loader": "^15.8.3",
|
|
172
178
|
"vue-loader-vue3": "npm:vue-loader@17",
|
|
@@ -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,
|
package/src/scss/storybook.scss
CHANGED
package/src/scss/utilities.scss
CHANGED
|
@@ -6510,6 +6510,16 @@ $gl-animate-skeleton-loader-max-width: 64 * $grid-size;
|
|
|
6510
6510
|
.gl-mr-auto\! {
|
|
6511
6511
|
margin-right: auto !important;
|
|
6512
6512
|
}
|
|
6513
|
+
.gl-md-mr-auto {
|
|
6514
|
+
@include gl-media-breakpoint-up(md) {
|
|
6515
|
+
margin-right: auto;
|
|
6516
|
+
}
|
|
6517
|
+
}
|
|
6518
|
+
.gl-md-mr-auto\! {
|
|
6519
|
+
@include gl-media-breakpoint-up(md) {
|
|
6520
|
+
margin-right: auto !important;
|
|
6521
|
+
}
|
|
6522
|
+
}
|
|
6513
6523
|
.gl-mr-0 {
|
|
6514
6524
|
margin-right: 0;
|
|
6515
6525
|
}
|