@gitlab/ui 128.11.0 → 128.13.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/dist/components/base/attribute_list/attribute_list.js +1 -1
- package/dist/components/base/form/form_group/form_group.js +12 -3
- package/dist/components/base/new_dropdowns/base_dropdown/base_dropdown.js +53 -5
- package/dist/components/base/new_dropdowns/listbox/listbox.js +17 -4
- package/dist/index.css +1 -1
- package/dist/index.css.map +1 -1
- package/dist/vendor/bootstrap-vue/src/components/form-group/form-group.js +2 -1
- package/package.json +8 -7
- package/src/components/base/attribute_list/attribute_list.vue +1 -1
- package/src/components/base/form/form_group/form_group.vue +17 -3
- package/src/components/base/new_dropdowns/base_dropdown/base_dropdown.vue +54 -3
- package/src/components/base/new_dropdowns/dropdown.scss +8 -0
- package/src/components/base/new_dropdowns/listbox/listbox.vue +17 -3
- package/src/vendor/bootstrap-vue/src/components/form-group/form-group.js +2 -1
|
@@ -53,6 +53,7 @@ const generateProps = () => makePropsConfigurable(sortKeys({
|
|
|
53
53
|
label: makeProp(PROP_TYPE_STRING),
|
|
54
54
|
labelClass: makeProp(PROP_TYPE_ARRAY_OBJECT_STRING),
|
|
55
55
|
labelFor: makeProp(PROP_TYPE_STRING),
|
|
56
|
+
labelId: makeProp(PROP_TYPE_STRING),
|
|
56
57
|
labelSize: makeProp(PROP_TYPE_STRING),
|
|
57
58
|
labelSrOnly: makeProp(PROP_TYPE_BOOLEAN, false),
|
|
58
59
|
tooltip: makeProp(PROP_TYPE_BOOLEAN, false),
|
|
@@ -209,7 +210,7 @@ const BFormGroup = {
|
|
|
209
210
|
const isFieldset = !labelFor;
|
|
210
211
|
let $label = h();
|
|
211
212
|
const labelContent = normalizeSlot(SLOT_NAME_LABEL) || this.label;
|
|
212
|
-
const labelId = labelContent ? safeId('_BV_label_') : null;
|
|
213
|
+
const labelId = labelContent ? this.labelId || safeId('_BV_label_') : null;
|
|
213
214
|
if (labelContent || isHorizontal) {
|
|
214
215
|
const {
|
|
215
216
|
labelSize,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gitlab/ui",
|
|
3
|
-
"version": "128.
|
|
3
|
+
"version": "128.13.0",
|
|
4
4
|
"description": "GitLab UI Components",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -37,6 +37,7 @@
|
|
|
37
37
|
"prebuild": "yarn build-tokens",
|
|
38
38
|
"copy-fonts": "make copy-fonts",
|
|
39
39
|
"build-tokens": "make tokens",
|
|
40
|
+
"sync-tokens": "node --env-file=.figma.env bin/figma_sync_tokens.mjs",
|
|
40
41
|
"clean": "rm -r dist storybook",
|
|
41
42
|
"cy:edge": "cypress run --browser edge --env grepTags=-@storybook",
|
|
42
43
|
"cy:run": "cypress run --browser firefox --env grepTags=-@storybook",
|
|
@@ -131,7 +132,7 @@
|
|
|
131
132
|
"autoprefixer": "10.4.24",
|
|
132
133
|
"axe-playwright": "^2.2.2",
|
|
133
134
|
"babel-loader": "^9.2.1",
|
|
134
|
-
"cypress": "15.
|
|
135
|
+
"cypress": "15.10.0",
|
|
135
136
|
"cypress-real-events": "^1.15.0",
|
|
136
137
|
"dompurify": "^3.1.2",
|
|
137
138
|
"emoji-regex": "^10.6.0",
|
|
@@ -142,12 +143,12 @@
|
|
|
142
143
|
"jest-circus": "30.2.0",
|
|
143
144
|
"jest-environment-jsdom": "30.2.0",
|
|
144
145
|
"jest-image-snapshot": "^6.5.1",
|
|
145
|
-
"merge-cobertura": "^1.0.
|
|
146
|
+
"merge-cobertura": "^1.0.5",
|
|
146
147
|
"mockdate": "^3.0.5",
|
|
147
|
-
"module-alias": "^2.
|
|
148
|
+
"module-alias": "^2.3.4",
|
|
148
149
|
"pikaday": "^1.8.0",
|
|
149
|
-
"playwright": "^1.58.
|
|
150
|
-
"playwright-core": "^1.58.
|
|
150
|
+
"playwright": "^1.58.2",
|
|
151
|
+
"playwright-core": "^1.58.2",
|
|
151
152
|
"postcss": "8.5.6",
|
|
152
153
|
"postcss-loader": "8.2.0",
|
|
153
154
|
"postcss-scss": "4.0.9",
|
|
@@ -165,7 +166,7 @@
|
|
|
165
166
|
"start-server-and-test": "^2.1.3",
|
|
166
167
|
"storybook": "^7.6.20",
|
|
167
168
|
"storybook-dark-mode": "4.0.2",
|
|
168
|
-
"style-dictionary": "^5.
|
|
169
|
+
"style-dictionary": "^5.3.0",
|
|
169
170
|
"style-loader": "^4",
|
|
170
171
|
"tailwindcss": "3.4.19",
|
|
171
172
|
"vue": "2.7.16",
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<script>
|
|
2
2
|
import isString from 'lodash/isString';
|
|
3
3
|
import isPlainObject from 'lodash/isPlainObject';
|
|
4
|
+
import { uniqueId } from 'lodash';
|
|
4
5
|
import { BFormGroup } from '../../../../vendor/bootstrap-vue/src/components/form-group/form-group';
|
|
5
6
|
|
|
6
7
|
export default {
|
|
@@ -8,8 +9,11 @@ export default {
|
|
|
8
9
|
components: {
|
|
9
10
|
BFormGroup,
|
|
10
11
|
},
|
|
11
|
-
provide
|
|
12
|
-
|
|
12
|
+
provide() {
|
|
13
|
+
return {
|
|
14
|
+
// Only for internal use by @gitlab/ui components
|
|
15
|
+
getFormGroupInstance: () => this,
|
|
16
|
+
};
|
|
13
17
|
},
|
|
14
18
|
inheritAttrs: false,
|
|
15
19
|
props: {
|
|
@@ -46,6 +50,11 @@ export default {
|
|
|
46
50
|
default: '(optional)',
|
|
47
51
|
},
|
|
48
52
|
},
|
|
53
|
+
data() {
|
|
54
|
+
return {
|
|
55
|
+
labelId: uniqueId('gl-form-group-label-'),
|
|
56
|
+
};
|
|
57
|
+
},
|
|
49
58
|
computed: {
|
|
50
59
|
actualLabelClass() {
|
|
51
60
|
const { labelClass } = this;
|
|
@@ -70,7 +79,12 @@ export default {
|
|
|
70
79
|
};
|
|
71
80
|
</script>
|
|
72
81
|
<template>
|
|
73
|
-
<b-form-group
|
|
82
|
+
<b-form-group
|
|
83
|
+
v-bind="$attrs"
|
|
84
|
+
class="gl-form-group"
|
|
85
|
+
:label-class="actualLabelClass"
|
|
86
|
+
:label-id="labelId"
|
|
87
|
+
>
|
|
74
88
|
<template v-if="$attrs.label || $scopedSlots.label" #label>
|
|
75
89
|
<slot name="label">
|
|
76
90
|
{{ $attrs.label }}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<script>
|
|
2
2
|
import uniqueId from 'lodash/uniqueId';
|
|
3
|
+
import isBoolean from 'lodash/isBoolean';
|
|
3
4
|
import {
|
|
4
5
|
arrow,
|
|
5
6
|
computePosition,
|
|
@@ -55,6 +56,11 @@ export default {
|
|
|
55
56
|
GlIcon,
|
|
56
57
|
},
|
|
57
58
|
directives: { Outside: OutsideDirective },
|
|
59
|
+
inject: {
|
|
60
|
+
getFormGroupInstance: {
|
|
61
|
+
default: () => () => {},
|
|
62
|
+
},
|
|
63
|
+
},
|
|
58
64
|
props: {
|
|
59
65
|
toggleText: {
|
|
60
66
|
type: String,
|
|
@@ -114,6 +120,14 @@ export default {
|
|
|
114
120
|
required: false,
|
|
115
121
|
default: false,
|
|
116
122
|
},
|
|
123
|
+
/**
|
|
124
|
+
* Controls the validation state appearance of the component. `true` for valid, `false` for invalid, or `null` for no validation state
|
|
125
|
+
*/
|
|
126
|
+
state: {
|
|
127
|
+
type: Boolean,
|
|
128
|
+
required: false,
|
|
129
|
+
default: null,
|
|
130
|
+
},
|
|
117
131
|
placement: {
|
|
118
132
|
type: String,
|
|
119
133
|
required: false,
|
|
@@ -240,6 +254,15 @@ export default {
|
|
|
240
254
|
isCaretOnly() {
|
|
241
255
|
return !this.noCaret && !this.icon && this.hasNoVisibleToggleText;
|
|
242
256
|
},
|
|
257
|
+
computedState() {
|
|
258
|
+
// If not a boolean, ensure that value is null
|
|
259
|
+
return isBoolean(this.state) ? this.state : null;
|
|
260
|
+
},
|
|
261
|
+
stateClass() {
|
|
262
|
+
if (this.computedState === true) return 'is-valid';
|
|
263
|
+
if (this.computedState === false) return 'is-invalid';
|
|
264
|
+
return null;
|
|
265
|
+
},
|
|
243
266
|
isDefaultToggle() {
|
|
244
267
|
return !this.$scopedSlots.toggle;
|
|
245
268
|
},
|
|
@@ -293,21 +316,49 @@ export default {
|
|
|
293
316
|
'gl-new-dropdown-toggle-no-caret': this.noCaret,
|
|
294
317
|
'gl-new-dropdown-caret-only btn-icon': this.isCaretOnly,
|
|
295
318
|
},
|
|
319
|
+
this.stateClass,
|
|
296
320
|
];
|
|
297
321
|
},
|
|
298
322
|
toggleButtonTextClasses() {
|
|
299
323
|
return this.block ? 'gl-w-full' : '';
|
|
300
324
|
},
|
|
325
|
+
// Set the aria-labelledby property with one or more ID strings
|
|
301
326
|
toggleLabelledBy() {
|
|
327
|
+
const formGroupLabelId = this.getFormGroupInstance()?.labelId;
|
|
328
|
+
|
|
302
329
|
if (this.isToggleCombobox) {
|
|
330
|
+
// Comboboxes announce label and self value when aria-labelledby is label ID.
|
|
331
|
+
// Tested with VoiceOver, NVDA, JAWS, Narrator and preferred browsers.
|
|
332
|
+
if (this.ariaLabelledby) {
|
|
333
|
+
return `${this.ariaLabelledby}`;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
// Combobox inside GlFormGroup
|
|
337
|
+
if (formGroupLabelId) {
|
|
338
|
+
return `${formGroupLabelId} ${this.toggleId}`;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
// Fallback calculated toggleId value
|
|
342
|
+
return this.toggleId;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
if (!this.isToggleCombobox) {
|
|
346
|
+
// Disclosures or buttons with listbox require both IDs to announce correctly.
|
|
347
|
+
// Tested with VoiceOver, NVDA, JAWS, Narrator and preferred browsers.
|
|
303
348
|
if (this.ariaLabelledby) {
|
|
304
349
|
return `${this.ariaLabelledby} ${this.toggleId}`;
|
|
305
350
|
}
|
|
351
|
+
|
|
352
|
+
// Disclosure or button with listbox inside GlFormGroup
|
|
353
|
+
if (formGroupLabelId) {
|
|
354
|
+
return `${formGroupLabelId} ${this.toggleId}`;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
// Fallback calculated toggleId value
|
|
306
358
|
return this.toggleId;
|
|
307
359
|
}
|
|
308
360
|
|
|
309
|
-
|
|
310
|
-
return this.ariaLabelledby ? `${this.ariaLabelledby} ${this.toggleId}` : undefined;
|
|
361
|
+
return undefined;
|
|
311
362
|
},
|
|
312
363
|
toggleRole() {
|
|
313
364
|
if (this.isToggleCombobox) {
|
|
@@ -558,7 +609,7 @@ export default {
|
|
|
558
609
|
this.$emit(GL_DROPDOWN_SHOWN);
|
|
559
610
|
} else {
|
|
560
611
|
this.stopFloating();
|
|
561
|
-
this.$emit(GL_DROPDOWN_HIDDEN);
|
|
612
|
+
this.$emit(GL_DROPDOWN_HIDDEN, event);
|
|
562
613
|
}
|
|
563
614
|
|
|
564
615
|
// this is to check whether `toggle` was prevented or not
|
|
@@ -67,8 +67,8 @@ export default {
|
|
|
67
67
|
GlIntersectionObserver,
|
|
68
68
|
},
|
|
69
69
|
inject: {
|
|
70
|
-
|
|
71
|
-
default:
|
|
70
|
+
getFormGroupInstance: {
|
|
71
|
+
default: () => () => {},
|
|
72
72
|
},
|
|
73
73
|
},
|
|
74
74
|
model: {
|
|
@@ -166,6 +166,14 @@ export default {
|
|
|
166
166
|
required: false,
|
|
167
167
|
default: false,
|
|
168
168
|
},
|
|
169
|
+
/**
|
|
170
|
+
* Controls the validation state appearance of the component. `true` for valid, `false` for invalid, or `null` for no validation state
|
|
171
|
+
*/
|
|
172
|
+
state: {
|
|
173
|
+
type: Boolean,
|
|
174
|
+
required: false,
|
|
175
|
+
default: null,
|
|
176
|
+
},
|
|
169
177
|
/**
|
|
170
178
|
* Set to "true" when dropdown content (items) is loading
|
|
171
179
|
* It will render a small loader in the dropdown toggle and make it disabled
|
|
@@ -417,6 +425,9 @@ export default {
|
|
|
417
425
|
// Fallback. Return a header ID or the toggle button ID.
|
|
418
426
|
return this.listAriaLabelledBy || this.headerId || this.toggleIdComputed;
|
|
419
427
|
},
|
|
428
|
+
isInFormGroup() {
|
|
429
|
+
return Boolean(this.getFormGroupInstance());
|
|
430
|
+
},
|
|
420
431
|
toggleIdComputed() {
|
|
421
432
|
return this.toggleId || uniqueId('dropdown-toggle-btn-');
|
|
422
433
|
},
|
|
@@ -684,7 +695,7 @@ export default {
|
|
|
684
695
|
*/
|
|
685
696
|
this.$emit(GL_DROPDOWN_SHOWN);
|
|
686
697
|
},
|
|
687
|
-
onHide() {
|
|
698
|
+
onHide(event) {
|
|
688
699
|
/**
|
|
689
700
|
* Emitted when dropdown is hidden
|
|
690
701
|
*
|
|
@@ -692,6 +703,8 @@ export default {
|
|
|
692
703
|
*/
|
|
693
704
|
this.$emit(GL_DROPDOWN_HIDDEN);
|
|
694
705
|
this.nextFocusedItemIndex = null;
|
|
706
|
+
// Emit native blur event for form validation in FormGroup
|
|
707
|
+
this.$emit('blur', event);
|
|
695
708
|
},
|
|
696
709
|
getNextIndex(currentIndex, keyCode, totalLength) {
|
|
697
710
|
// For UP: move up or wrap to end
|
|
@@ -974,6 +987,7 @@ export default {
|
|
|
974
987
|
:has-searchable-listbox="searchable"
|
|
975
988
|
:has-external-label="isInFormGroup"
|
|
976
989
|
:listbox-id="listboxIdComputed"
|
|
990
|
+
:state="state"
|
|
977
991
|
:toggle-id="toggleIdComputed"
|
|
978
992
|
:toggle-text="listboxToggleText"
|
|
979
993
|
:toggle-class="toggleButtonClasses"
|
|
@@ -74,6 +74,7 @@ export const generateProps = () =>
|
|
|
74
74
|
label: makeProp(PROP_TYPE_STRING),
|
|
75
75
|
labelClass: makeProp(PROP_TYPE_ARRAY_OBJECT_STRING),
|
|
76
76
|
labelFor: makeProp(PROP_TYPE_STRING),
|
|
77
|
+
labelId: makeProp(PROP_TYPE_STRING),
|
|
77
78
|
labelSize: makeProp(PROP_TYPE_STRING),
|
|
78
79
|
labelSrOnly: makeProp(PROP_TYPE_BOOLEAN, false),
|
|
79
80
|
tooltip: makeProp(PROP_TYPE_BOOLEAN, false),
|
|
@@ -241,7 +242,7 @@ export const BFormGroup = {
|
|
|
241
242
|
|
|
242
243
|
let $label = h()
|
|
243
244
|
const labelContent = normalizeSlot(SLOT_NAME_LABEL) || this.label
|
|
244
|
-
const labelId = labelContent ? safeId('_BV_label_') : null
|
|
245
|
+
const labelId = labelContent ? this.labelId || safeId('_BV_label_') : null
|
|
245
246
|
if (labelContent || isHorizontal) {
|
|
246
247
|
const { labelSize, labelColProps } = this
|
|
247
248
|
const labelTag = isFieldset ? 'legend' : 'label'
|