@gitlab/ui 127.1.1 → 128.1.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/form/form_checkbox/form_checkbox.js +0 -3
- package/dist/components/base/form/form_checkbox/form_checkbox_group.js +132 -3
- package/dist/components/base/form/form_group/form_group.js +3 -0
- package/dist/components/base/new_dropdowns/base_dropdown/base_dropdown.js +95 -20
- package/dist/components/base/new_dropdowns/disclosure/disclosure_dropdown.js +1 -1
- package/dist/components/base/new_dropdowns/listbox/listbox.js +47 -10
- package/dist/index.css +1 -1
- package/dist/index.css.map +1 -1
- package/dist/tailwind.css +1 -1
- package/dist/tailwind.css.map +1 -1
- package/dist/tokens/build/js/tokens.dark.js +127 -127
- package/dist/tokens/build/js/tokens.js +110 -110
- package/dist/vendor/bootstrap-vue/src/constants/components.js +1 -3
- package/dist/vendor/bootstrap-vue/src/mixins/form-radio-check-group.js +1 -2
- package/package.json +1 -1
- package/src/components/base/form/form_checkbox/form_checkbox.vue +0 -3
- package/src/components/base/form/form_checkbox/form_checkbox_group.vue +148 -21
- package/src/components/base/form/form_group/form_group.vue +3 -0
- package/src/components/base/new_dropdowns/base_dropdown/base_dropdown.vue +101 -22
- package/src/components/base/new_dropdowns/disclosure/disclosure_dropdown.vue +3 -2
- package/src/components/base/new_dropdowns/listbox/listbox.vue +52 -9
- package/src/scss/bootstrap_vue.scss +0 -1
- package/src/tokens/build/css/tokens.css +24 -24
- package/src/tokens/build/css/tokens.dark.css +26 -26
- package/src/tokens/build/docs/tokens-tailwind-docs.dark.json +82 -82
- package/src/tokens/build/docs/tokens-tailwind-docs.json +81 -81
- package/src/tokens/build/figma/constants.tokens.json +2245 -226
- package/src/tokens/build/figma/contextual.tokens.json +753 -77
- package/src/tokens/build/figma/deprecated.tokens.json +4151 -420
- package/src/tokens/build/figma/semantic.tokens.json +171 -19
- package/src/tokens/build/js/tokens.dark.js +130 -127
- package/src/tokens/build/js/tokens.js +113 -110
- package/src/tokens/build/json/tokens.dark.json +161 -161
- package/src/tokens/build/json/tokens.json +142 -142
- package/src/tokens/build/scss/_tokens.dark.scss +26 -26
- package/src/tokens/build/scss/_tokens.scss +24 -24
- package/src/tokens/constant/color.alpha.tokens.json +135 -15
- package/src/tokens/constant/color.tokens.json +2110 -211
- package/src/tokens/contextual/avatar.tokens.json +54 -6
- package/src/tokens/contextual/button.tokens.json +90 -10
- package/src/tokens/contextual/chart.tokens.json +9 -1
- package/src/tokens/contextual/illustration.tokens.json +600 -60
- package/src/tokens/deprecated/deprecated.color.data_viz.tokens.json +1100 -110
- package/src/tokens/deprecated/deprecated.color.theme.tokens.json +1440 -144
- package/src/tokens/deprecated/deprecated.color.tokens.json +1490 -149
- package/src/tokens/deprecated/deprecated.color.transparency.tokens.json +147 -43
- package/src/tokens/semantic/action.tokens.json +162 -18
- package/src/tokens/semantic/background.tokens.json +9 -1
- package/src/vendor/bootstrap-vue/src/constants/components.js +0 -2
- package/src/vendor/bootstrap-vue/src/mixins/form-radio-check-group.js +1 -2
- package/dist/vendor/bootstrap-vue/src/components/form-checkbox/form-checkbox-group.js +0 -37
- package/dist/vendor/bootstrap-vue/src/components/form-checkbox/form-checkbox.js +0 -134
- package/dist/vendor/bootstrap-vue/src/components/form-checkbox/index.js +0 -2
- package/src/vendor/bootstrap-vue/src/components/form-checkbox/_form-checkbox-group.scss +0 -1
- package/src/vendor/bootstrap-vue/src/components/form-checkbox/_form-checkbox.scss +0 -125
- package/src/vendor/bootstrap-vue/src/components/form-checkbox/form-checkbox-group.js +0 -42
- package/src/vendor/bootstrap-vue/src/components/form-checkbox/form-checkbox.js +0 -132
- package/src/vendor/bootstrap-vue/src/components/form-checkbox/index.js +0 -4
- package/src/vendor/bootstrap-vue/src/components/form-checkbox/index.scss +0 -2
|
@@ -1,44 +1,171 @@
|
|
|
1
1
|
<script>
|
|
2
|
+
import uniqueId from 'lodash/uniqueId';
|
|
3
|
+
import isBoolean from 'lodash/isBoolean';
|
|
4
|
+
import omit from 'lodash/omit';
|
|
5
|
+
import pick from 'lodash/pick';
|
|
6
|
+
import { looseEqual } from '../../../../vendor/bootstrap-vue/src/utils/loose-equal';
|
|
2
7
|
import { formOptionsMixin } from '../../../../vendor/bootstrap-vue/src/mixins/form-options';
|
|
3
|
-
import { BFormCheckboxGroup } from '../../../../vendor/bootstrap-vue/src/components/form-checkbox/form-checkbox-group';
|
|
4
8
|
import { SafeHtmlDirective as SafeHtml } from '../../../../directives/safe_html/safe_html';
|
|
5
9
|
import GlFormCheckbox from './form_checkbox.vue';
|
|
6
10
|
|
|
11
|
+
// Attributes to pass down to checks/radios instead of applying them to the group
|
|
12
|
+
const PASS_DOWN_ATTRS = ['aria-describedby', 'aria-labelledby'];
|
|
13
|
+
|
|
7
14
|
export default {
|
|
8
15
|
name: 'GlFormCheckboxGroup',
|
|
9
|
-
components: {
|
|
16
|
+
components: { GlFormCheckbox },
|
|
10
17
|
directives: {
|
|
11
18
|
SafeHtml,
|
|
12
19
|
},
|
|
13
20
|
mixins: [formOptionsMixin],
|
|
21
|
+
provide() {
|
|
22
|
+
return {
|
|
23
|
+
getGroup: () => this,
|
|
24
|
+
};
|
|
25
|
+
},
|
|
14
26
|
inheritAttrs: false,
|
|
15
27
|
model: {
|
|
16
28
|
prop: 'checked',
|
|
17
29
|
event: 'input',
|
|
18
30
|
},
|
|
31
|
+
props: {
|
|
32
|
+
/**
|
|
33
|
+
* Used to set the `id` attribute on the rendered content, and used as the base to generate any additional element IDs as needed.
|
|
34
|
+
*/
|
|
35
|
+
id: {
|
|
36
|
+
type: String,
|
|
37
|
+
required: false,
|
|
38
|
+
default: undefined,
|
|
39
|
+
},
|
|
40
|
+
/**
|
|
41
|
+
* The current value of the checkbox.
|
|
42
|
+
*/
|
|
43
|
+
checked: {
|
|
44
|
+
type: Array,
|
|
45
|
+
required: false,
|
|
46
|
+
default: () => [],
|
|
47
|
+
},
|
|
48
|
+
/**
|
|
49
|
+
* Array of items to render in the component
|
|
50
|
+
*/
|
|
51
|
+
options: {
|
|
52
|
+
type: Array,
|
|
53
|
+
required: false,
|
|
54
|
+
default: () => [],
|
|
55
|
+
},
|
|
56
|
+
/**
|
|
57
|
+
* When set to `true`, disables the component's functionality and places it in a disabled state.
|
|
58
|
+
*/
|
|
59
|
+
disabled: {
|
|
60
|
+
type: Boolean,
|
|
61
|
+
required: false,
|
|
62
|
+
default: false,
|
|
63
|
+
},
|
|
64
|
+
/**
|
|
65
|
+
* Sets the value of the `name` attribute on the form control.
|
|
66
|
+
*/
|
|
67
|
+
name: {
|
|
68
|
+
type: String,
|
|
69
|
+
required: false,
|
|
70
|
+
default: undefined,
|
|
71
|
+
},
|
|
72
|
+
/**
|
|
73
|
+
* Adds the `required` attribute to the form control.
|
|
74
|
+
*/
|
|
75
|
+
required: {
|
|
76
|
+
type: Boolean,
|
|
77
|
+
required: false,
|
|
78
|
+
default: false,
|
|
79
|
+
},
|
|
80
|
+
/**
|
|
81
|
+
* Controls the validation state appearance of the component. `true` for valid, `false` for invalid, or `null` for no validation state.
|
|
82
|
+
*/
|
|
83
|
+
state: {
|
|
84
|
+
type: Boolean,
|
|
85
|
+
required: false,
|
|
86
|
+
default: null,
|
|
87
|
+
},
|
|
88
|
+
/**
|
|
89
|
+
* Optional value to set for the 'aria-invalid' attribute. Supported values are 'true' and 'false'. If not set, the 'state' prop will dictate the value
|
|
90
|
+
*/
|
|
91
|
+
ariaInvalid: {
|
|
92
|
+
type: [Boolean, String],
|
|
93
|
+
required: false,
|
|
94
|
+
default: false,
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
data() {
|
|
98
|
+
return {
|
|
99
|
+
internalId: this.id ? this.id : uniqueId('gitlab_ui_checkbox_group_'),
|
|
100
|
+
localChecked: this.checked,
|
|
101
|
+
};
|
|
102
|
+
},
|
|
103
|
+
computed: {
|
|
104
|
+
computedState() {
|
|
105
|
+
return isBoolean(this.state) ? this.state : null;
|
|
106
|
+
},
|
|
107
|
+
stateClass() {
|
|
108
|
+
if (this.computedState === true) return 'is-valid';
|
|
109
|
+
if (this.computedState === false) return 'is-invalid';
|
|
110
|
+
return null;
|
|
111
|
+
},
|
|
112
|
+
computedAriaInvalid() {
|
|
113
|
+
const { ariaInvalid } = this;
|
|
114
|
+
if (ariaInvalid === true || ariaInvalid === 'true' || ariaInvalid === '') {
|
|
115
|
+
return 'true';
|
|
116
|
+
}
|
|
117
|
+
return this.computedState === false ? 'true' : ariaInvalid;
|
|
118
|
+
},
|
|
119
|
+
computedAttrs() {
|
|
120
|
+
return {
|
|
121
|
+
...omit(this.$attrs, PASS_DOWN_ATTRS),
|
|
122
|
+
id: this.internalId,
|
|
123
|
+
'aria-invalid': this.computedAriaInvalid,
|
|
124
|
+
'aria-required': this.required || null,
|
|
125
|
+
};
|
|
126
|
+
},
|
|
127
|
+
passDownAttrs() {
|
|
128
|
+
return pick(this.$attrs, PASS_DOWN_ATTRS);
|
|
129
|
+
},
|
|
130
|
+
groupName() {
|
|
131
|
+
// Checks/Radios tied to the same model must have the same name,
|
|
132
|
+
// especially for ARIA accessibility
|
|
133
|
+
return this.name || this.internalId;
|
|
134
|
+
},
|
|
135
|
+
},
|
|
136
|
+
watch: {
|
|
137
|
+
checked(newValue) {
|
|
138
|
+
if (!looseEqual(newValue, this.localChecked)) {
|
|
139
|
+
this.localChecked = newValue;
|
|
140
|
+
}
|
|
141
|
+
},
|
|
142
|
+
localChecked(newValue, oldValue) {
|
|
143
|
+
if (!looseEqual(newValue, oldValue)) {
|
|
144
|
+
this.$emit('input', newValue);
|
|
145
|
+
}
|
|
146
|
+
},
|
|
147
|
+
},
|
|
19
148
|
};
|
|
20
149
|
</script>
|
|
21
150
|
|
|
22
151
|
<template>
|
|
23
|
-
<div
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
152
|
+
<div
|
|
153
|
+
v-bind="computedAttrs"
|
|
154
|
+
role="group"
|
|
155
|
+
tabindex="-1"
|
|
156
|
+
class="gl-form-checkbox-group gl-outline-none"
|
|
157
|
+
>
|
|
158
|
+
<slot name="first"></slot>
|
|
159
|
+
<gl-form-checkbox
|
|
160
|
+
v-for="(option, idx) in formOptions"
|
|
161
|
+
v-bind="passDownAttrs"
|
|
162
|
+
:key="idx"
|
|
163
|
+
:value="option.value"
|
|
164
|
+
:disabled="option.disabled"
|
|
30
165
|
>
|
|
31
|
-
<
|
|
32
|
-
<
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
:value="option.value"
|
|
36
|
-
:disabled="option.disabled"
|
|
37
|
-
>
|
|
38
|
-
<span v-if="option.html" v-safe-html="option.html"></span>
|
|
39
|
-
<span v-else>{{ option.text }}</span>
|
|
40
|
-
</gl-form-checkbox>
|
|
41
|
-
<slot></slot>
|
|
42
|
-
</b-form-checkbox-group>
|
|
166
|
+
<span v-if="option.html" v-safe-html="option.html"></span>
|
|
167
|
+
<span v-else>{{ option.text }}</span>
|
|
168
|
+
</gl-form-checkbox>
|
|
169
|
+
<slot></slot>
|
|
43
170
|
</div>
|
|
44
171
|
</template>
|
|
@@ -138,6 +138,26 @@ export default {
|
|
|
138
138
|
return ['menu', 'listbox', 'tree', 'grid', 'dialog', true, false].includes(value);
|
|
139
139
|
},
|
|
140
140
|
},
|
|
141
|
+
activeItemId: {
|
|
142
|
+
type: String,
|
|
143
|
+
required: false,
|
|
144
|
+
default: undefined,
|
|
145
|
+
},
|
|
146
|
+
hasExternalLabel: {
|
|
147
|
+
type: Boolean,
|
|
148
|
+
required: false,
|
|
149
|
+
default: false,
|
|
150
|
+
},
|
|
151
|
+
hasSearchableListbox: {
|
|
152
|
+
type: Boolean,
|
|
153
|
+
required: false,
|
|
154
|
+
default: false,
|
|
155
|
+
},
|
|
156
|
+
isDisclosure: {
|
|
157
|
+
type: Boolean,
|
|
158
|
+
required: false,
|
|
159
|
+
default: false,
|
|
160
|
+
},
|
|
141
161
|
/**
|
|
142
162
|
* Id that will be referenced by `aria-labelledby` attribute of the dropdown content`
|
|
143
163
|
*/
|
|
@@ -145,6 +165,15 @@ export default {
|
|
|
145
165
|
type: String,
|
|
146
166
|
required: true,
|
|
147
167
|
},
|
|
168
|
+
/**
|
|
169
|
+
* Span Id that will be referenced by listbox `aria-labelledby` if there's an external label.
|
|
170
|
+
* This prop will only be defined by `GlCollapsibleListbox` when `isInFormGroup` injected is true.
|
|
171
|
+
*/
|
|
172
|
+
listboxId: {
|
|
173
|
+
type: String,
|
|
174
|
+
required: false,
|
|
175
|
+
default: undefined,
|
|
176
|
+
},
|
|
148
177
|
/**
|
|
149
178
|
* The `aria-labelledby` attribute value for the toggle `button`
|
|
150
179
|
*/
|
|
@@ -187,6 +216,10 @@ export default {
|
|
|
187
216
|
};
|
|
188
217
|
},
|
|
189
218
|
computed: {
|
|
219
|
+
ariaActiveDescendant() {
|
|
220
|
+
if (!this.isDisclosure && this.visible) return this.activeItemId;
|
|
221
|
+
return undefined;
|
|
222
|
+
},
|
|
190
223
|
hasNoVisibleToggleText() {
|
|
191
224
|
return !this.toggleText?.length || this.textSrOnly;
|
|
192
225
|
},
|
|
@@ -199,12 +232,47 @@ export default {
|
|
|
199
232
|
isCaretOnly() {
|
|
200
233
|
return !this.noCaret && !this.icon && this.hasNoVisibleToggleText;
|
|
201
234
|
},
|
|
202
|
-
|
|
235
|
+
isDefaultToggle() {
|
|
236
|
+
return !this.$scopedSlots.toggle;
|
|
237
|
+
},
|
|
238
|
+
isToggleCombobox() {
|
|
239
|
+
if (this.hasSearchableListbox || this.isDisclosure) {
|
|
240
|
+
return false;
|
|
241
|
+
}
|
|
242
|
+
return true;
|
|
243
|
+
},
|
|
244
|
+
isToggleLabelledExternally() {
|
|
245
|
+
if (this.hasExternalLabel && this.toggleId) return true;
|
|
246
|
+
return false;
|
|
247
|
+
},
|
|
248
|
+
computedToggleId() {
|
|
249
|
+
if (this.isDisclosure) {
|
|
250
|
+
return this.isDefaultToggle ? this.toggleId : undefined;
|
|
251
|
+
}
|
|
252
|
+
if (this.isToggleLabelledExternally) {
|
|
253
|
+
return this.isDefaultToggle ? this.toggleId : undefined;
|
|
254
|
+
}
|
|
255
|
+
if (this.hasSearchableListbox) {
|
|
256
|
+
return this.toggleId;
|
|
257
|
+
}
|
|
258
|
+
return undefined;
|
|
259
|
+
},
|
|
260
|
+
computedToggleInnerId() {
|
|
261
|
+
if (this.isToggleCombobox && !this.isToggleLabelledExternally) {
|
|
262
|
+
return this.toggleId;
|
|
263
|
+
}
|
|
264
|
+
if (this.isToggleCombobox && this.isToggleLabelledExternally) {
|
|
265
|
+
return this.listboxId;
|
|
266
|
+
}
|
|
267
|
+
return undefined;
|
|
268
|
+
},
|
|
269
|
+
toggleAriaAttributes() {
|
|
203
270
|
return {
|
|
204
|
-
'aria-haspopup': this.ariaHaspopup,
|
|
205
|
-
'aria-expanded': String(this.visible),
|
|
206
271
|
'aria-controls': this.baseDropdownId,
|
|
272
|
+
'aria-expanded': String(this.visible),
|
|
273
|
+
'aria-haspopup': this.ariaHaspopup,
|
|
207
274
|
'aria-labelledby': this.toggleLabelledBy,
|
|
275
|
+
'aria-activedescendant': this.ariaActiveDescendant,
|
|
208
276
|
};
|
|
209
277
|
},
|
|
210
278
|
toggleButtonClasses() {
|
|
@@ -223,10 +291,28 @@ export default {
|
|
|
223
291
|
return this.block ? 'gl-w-full' : '';
|
|
224
292
|
},
|
|
225
293
|
toggleLabelledBy() {
|
|
294
|
+
if (this.isToggleCombobox) {
|
|
295
|
+
if (this.ariaLabelledby) {
|
|
296
|
+
return `${this.ariaLabelledby} ${this.toggleId}`;
|
|
297
|
+
}
|
|
298
|
+
return this.toggleId;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
// For non-combobox toggles, combine IDs or use the button's own text
|
|
226
302
|
return this.ariaLabelledby ? `${this.ariaLabelledby} ${this.toggleId}` : undefined;
|
|
227
303
|
},
|
|
228
|
-
|
|
229
|
-
|
|
304
|
+
toggleRole() {
|
|
305
|
+
if (this.isToggleCombobox) {
|
|
306
|
+
return 'combobox';
|
|
307
|
+
}
|
|
308
|
+
return undefined;
|
|
309
|
+
},
|
|
310
|
+
toggleAccessibilityAttributes() {
|
|
311
|
+
return {
|
|
312
|
+
...this.toggleAriaAttributes,
|
|
313
|
+
id: this.toggleId,
|
|
314
|
+
role: this.toggleRole,
|
|
315
|
+
};
|
|
230
316
|
},
|
|
231
317
|
toggleOptions() {
|
|
232
318
|
if (this.isDefaultToggle) {
|
|
@@ -241,7 +327,8 @@ export default {
|
|
|
241
327
|
disabled: this.disabled,
|
|
242
328
|
loading: this.loading,
|
|
243
329
|
class: this.toggleButtonClasses,
|
|
244
|
-
|
|
330
|
+
role: this.toggleRole,
|
|
331
|
+
...this.toggleAriaAttributes,
|
|
245
332
|
listeners: {
|
|
246
333
|
keydown: (event) => this.onKeydown(event),
|
|
247
334
|
click: (event) => this.toggle(event),
|
|
@@ -264,7 +351,6 @@ export default {
|
|
|
264
351
|
|
|
265
352
|
toggleAttributes() {
|
|
266
353
|
const { listeners, is, ...attributes } = this.toggleOptions;
|
|
267
|
-
|
|
268
354
|
return attributes;
|
|
269
355
|
},
|
|
270
356
|
toggleComponent() {
|
|
@@ -325,18 +411,6 @@ export default {
|
|
|
325
411
|
};
|
|
326
412
|
},
|
|
327
413
|
},
|
|
328
|
-
watch: {
|
|
329
|
-
ariaAttributes: {
|
|
330
|
-
deep: true,
|
|
331
|
-
handler(ariaAttributes) {
|
|
332
|
-
if (this.$scopedSlots.toggle) {
|
|
333
|
-
Object.keys(ariaAttributes).forEach((key) => {
|
|
334
|
-
this.toggleElement.setAttribute(key, ariaAttributes[key]);
|
|
335
|
-
});
|
|
336
|
-
}
|
|
337
|
-
},
|
|
338
|
-
},
|
|
339
|
-
},
|
|
340
414
|
mounted() {
|
|
341
415
|
this.checkToggleFocusable();
|
|
342
416
|
},
|
|
@@ -593,14 +667,19 @@ export default {
|
|
|
593
667
|
<component
|
|
594
668
|
:is="toggleComponent"
|
|
595
669
|
v-bind="toggleAttributes"
|
|
596
|
-
:id="
|
|
670
|
+
:id="computedToggleId"
|
|
597
671
|
ref="toggle"
|
|
598
672
|
data-testid="base-dropdown-toggle"
|
|
599
673
|
v-on="toggleListeners"
|
|
600
674
|
>
|
|
601
675
|
<!-- @slot Custom toggle button content -->
|
|
602
|
-
<slot name="toggle">
|
|
603
|
-
<span
|
|
676
|
+
<slot name="toggle" :accessibility-attributes="toggleAccessibilityAttributes">
|
|
677
|
+
<span
|
|
678
|
+
:id="computedToggleInnerId"
|
|
679
|
+
class="gl-new-dropdown-button-text"
|
|
680
|
+
:class="{ 'gl-sr-only': textSrOnly }"
|
|
681
|
+
data-testid="base-dropdown-span"
|
|
682
|
+
>
|
|
604
683
|
{{ toggleText }}
|
|
605
684
|
</span>
|
|
606
685
|
<gl-icon
|
|
@@ -389,14 +389,15 @@ export default {
|
|
|
389
389
|
:fluid-width="fluidWidth"
|
|
390
390
|
:positioning-strategy="positioningStrategy"
|
|
391
391
|
class="gl-disclosure-dropdown"
|
|
392
|
+
is-disclosure
|
|
392
393
|
@[$options.events.GL_DROPDOWN_SHOWN]="onShow"
|
|
393
394
|
@[$options.events.GL_DROPDOWN_HIDDEN]="onHide"
|
|
394
395
|
@[$options.events.GL_DROPDOWN_BEFORE_CLOSE]="onBeforeClose"
|
|
395
396
|
@[$options.events.GL_DROPDOWN_FOCUS_CONTENT]="onKeydown"
|
|
396
397
|
>
|
|
397
|
-
<template v-if="hasCustomToggle" #toggle>
|
|
398
|
+
<template v-if="hasCustomToggle" #toggle="slotProps">
|
|
398
399
|
<!-- @slot Custom toggle content -->
|
|
399
|
-
<slot name="toggle"></slot>
|
|
400
|
+
<slot name="toggle" v-bind="slotProps"></slot>
|
|
400
401
|
</template>
|
|
401
402
|
|
|
402
403
|
<!-- @slot Content to display in dropdown header -->
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
ARROW_DOWN,
|
|
12
12
|
ARROW_UP,
|
|
13
13
|
GL_DROPDOWN_CONTENTS_CLASS,
|
|
14
|
+
GL_DROPDOWN_FOCUS_CONTENT,
|
|
14
15
|
POSITION_ABSOLUTE,
|
|
15
16
|
POSITION_FIXED,
|
|
16
17
|
} from '../constants';
|
|
@@ -53,6 +54,7 @@ export default {
|
|
|
53
54
|
events: {
|
|
54
55
|
GL_DROPDOWN_SHOWN,
|
|
55
56
|
GL_DROPDOWN_HIDDEN,
|
|
57
|
+
GL_DROPDOWN_FOCUS_CONTENT,
|
|
56
58
|
},
|
|
57
59
|
components: {
|
|
58
60
|
GlBaseDropdown,
|
|
@@ -64,6 +66,11 @@ export default {
|
|
|
64
66
|
GlLoadingIcon,
|
|
65
67
|
GlIntersectionObserver,
|
|
66
68
|
},
|
|
69
|
+
inject: {
|
|
70
|
+
isInFormGroup: {
|
|
71
|
+
default: false,
|
|
72
|
+
},
|
|
73
|
+
},
|
|
67
74
|
model: {
|
|
68
75
|
prop: 'selected',
|
|
69
76
|
event: 'select',
|
|
@@ -211,7 +218,7 @@ export default {
|
|
|
211
218
|
},
|
|
212
219
|
/**
|
|
213
220
|
* The `aria-labelledby` attribute value for the toggle button
|
|
214
|
-
* Provide the string of
|
|
221
|
+
* Provide the string of IDs seperated by space
|
|
215
222
|
*/
|
|
216
223
|
toggleAriaLabelledBy: {
|
|
217
224
|
type: String,
|
|
@@ -220,7 +227,7 @@ export default {
|
|
|
220
227
|
},
|
|
221
228
|
/**
|
|
222
229
|
* The `aria-labelledby` attribute value for the list of options
|
|
223
|
-
* Provide the string of
|
|
230
|
+
* Provide the string of IDs seperated by space
|
|
224
231
|
*/
|
|
225
232
|
listAriaLabelledBy: {
|
|
226
233
|
type: String,
|
|
@@ -382,15 +389,42 @@ export default {
|
|
|
382
389
|
};
|
|
383
390
|
},
|
|
384
391
|
computed: {
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
392
|
+
/**
|
|
393
|
+
* Determines the `aria-labelledby` attribute value for the listbox by
|
|
394
|
+
* evaluating a series of conditions in priority order. The returned ID
|
|
395
|
+
* references the element that best describes the listbox content, with
|
|
396
|
+
* preference given to headers in searchable lists, followed by search
|
|
397
|
+
* input, form labels, and finally fallback options.
|
|
398
|
+
*/
|
|
399
|
+
listboxAriaLabelledByID() {
|
|
400
|
+
// Listbox is labelled by closest heading, creating a meaningful relationship
|
|
401
|
+
if (this.headerId && this.searchable) return `${this.headerId}`;
|
|
402
|
+
|
|
403
|
+
// Listbox is labelled by the search input with role="combobox"
|
|
404
|
+
if (this.searchable) return this.searchInputId;
|
|
405
|
+
|
|
406
|
+
// Listbox is labelledy by the text inside an externally labelled button
|
|
407
|
+
if (this.isInFormGroup) return this.listboxIdComputed;
|
|
408
|
+
|
|
409
|
+
// Fallback. Return a header ID or the toggle button ID.
|
|
389
410
|
return this.listAriaLabelledBy || this.headerId || this.toggleIdComputed;
|
|
390
411
|
},
|
|
391
412
|
toggleIdComputed() {
|
|
392
413
|
return this.toggleId || uniqueId('dropdown-toggle-btn-');
|
|
393
414
|
},
|
|
415
|
+
// Generate a custom listbox ID when inside GlFormGroup
|
|
416
|
+
listboxIdComputed() {
|
|
417
|
+
if (this.isInFormGroup) {
|
|
418
|
+
if (this.listAriaLabelledBy) {
|
|
419
|
+
return this.listAriaLabelledBy;
|
|
420
|
+
}
|
|
421
|
+
if (this.toggleId) {
|
|
422
|
+
return `${this.toggleId}-span`;
|
|
423
|
+
}
|
|
424
|
+
return uniqueId('dropdown-toggle-span-');
|
|
425
|
+
}
|
|
426
|
+
return undefined;
|
|
427
|
+
},
|
|
394
428
|
listboxTag() {
|
|
395
429
|
if (!this.hasItems || isOption(this.items[0])) return 'ul';
|
|
396
430
|
return 'div';
|
|
@@ -606,6 +640,10 @@ export default {
|
|
|
606
640
|
this.scrollObserver?.disconnect();
|
|
607
641
|
},
|
|
608
642
|
methods: {
|
|
643
|
+
onFocusContent(event) {
|
|
644
|
+
event.preventDefault();
|
|
645
|
+
this.open();
|
|
646
|
+
},
|
|
609
647
|
open() {
|
|
610
648
|
this.$refs.baseDropdown.open();
|
|
611
649
|
},
|
|
@@ -922,8 +960,12 @@ export default {
|
|
|
922
960
|
<gl-base-dropdown
|
|
923
961
|
ref="baseDropdown"
|
|
924
962
|
aria-haspopup="listbox"
|
|
963
|
+
:active-item-id="activeItemId"
|
|
925
964
|
:aria-labelledby="toggleAriaLabelledBy"
|
|
926
965
|
:block="block"
|
|
966
|
+
:has-searchable-listbox="searchable"
|
|
967
|
+
:has-external-label="isInFormGroup"
|
|
968
|
+
:listbox-id="listboxIdComputed"
|
|
927
969
|
:toggle-id="toggleIdComputed"
|
|
928
970
|
:toggle-text="listboxToggleText"
|
|
929
971
|
:toggle-class="toggleButtonClasses"
|
|
@@ -939,12 +981,13 @@ export default {
|
|
|
939
981
|
:offset="dropdownOffset"
|
|
940
982
|
:fluid-width="fluidWidth"
|
|
941
983
|
:positioning-strategy="positioningStrategy"
|
|
984
|
+
@[$options.events.GL_DROPDOWN_FOCUS_CONTENT]="onFocusContent"
|
|
942
985
|
@[$options.events.GL_DROPDOWN_SHOWN]="onShow"
|
|
943
986
|
@[$options.events.GL_DROPDOWN_HIDDEN]="onHide"
|
|
944
987
|
>
|
|
945
|
-
<template v-if="hasCustomToggle" #toggle>
|
|
988
|
+
<template v-if="hasCustomToggle" #toggle="slotProps">
|
|
946
989
|
<!-- @slot Custom toggle content -->
|
|
947
|
-
<slot name="toggle"></slot>
|
|
990
|
+
<slot name="toggle" v-bind="slotProps"></slot>
|
|
948
991
|
</template>
|
|
949
992
|
|
|
950
993
|
<template #default="{ visible }">
|
|
@@ -1013,7 +1056,7 @@ export default {
|
|
|
1013
1056
|
:id="listboxId"
|
|
1014
1057
|
ref="list"
|
|
1015
1058
|
:aria-busy="isBusy"
|
|
1016
|
-
:aria-labelledby="
|
|
1059
|
+
:aria-labelledby="listboxAriaLabelledByID"
|
|
1017
1060
|
:aria-multiselectable="multiple ? 'true' : undefined"
|
|
1018
1061
|
role="listbox"
|
|
1019
1062
|
class="gl-new-dropdown-contents gl-new-dropdown-contents-with-scrim-overlay"
|
|
@@ -7,7 +7,6 @@ $bv-enable-popover-variants: false;
|
|
|
7
7
|
@import '../vendor/bootstrap-vue/src/utilities.scss';
|
|
8
8
|
|
|
9
9
|
@import '../vendor/bootstrap-vue/src/components/dropdown/index.scss';
|
|
10
|
-
@import '../vendor/bootstrap-vue/src/components/form-checkbox/index.scss';
|
|
11
10
|
@import '../vendor/bootstrap-vue/src/components/form-input/index.scss';
|
|
12
11
|
@import '../vendor/bootstrap-vue/src/components/form-radio/index.scss';
|
|
13
12
|
@import '../vendor/bootstrap-vue/src/components/modal/index.scss';
|
|
@@ -4,14 +4,14 @@
|
|
|
4
4
|
|
|
5
5
|
:root, .gl-light-scope {
|
|
6
6
|
--gl-border-radius-full: 9999px;
|
|
7
|
-
--gl-color-alpha-0:
|
|
8
|
-
--gl-color-alpha-dark-2: rgba(
|
|
9
|
-
--gl-color-alpha-dark-4: rgba(
|
|
10
|
-
--gl-color-alpha-dark-6: rgba(
|
|
11
|
-
--gl-color-alpha-dark-8: rgba(
|
|
12
|
-
--gl-color-alpha-dark-16: rgba(
|
|
13
|
-
--gl-color-alpha-dark-24: rgba(
|
|
14
|
-
--gl-color-alpha-dark-40: rgba(
|
|
7
|
+
--gl-color-alpha-0: rgba(0, 0, 0, 0);
|
|
8
|
+
--gl-color-alpha-dark-2: rgba(5, 5, 6, 0.02);
|
|
9
|
+
--gl-color-alpha-dark-4: rgba(5, 5, 6, 0.04);
|
|
10
|
+
--gl-color-alpha-dark-6: rgba(5, 5, 6, 0.06);
|
|
11
|
+
--gl-color-alpha-dark-8: rgba(5, 5, 6, 0.08);
|
|
12
|
+
--gl-color-alpha-dark-16: rgba(5, 5, 6, 0.16);
|
|
13
|
+
--gl-color-alpha-dark-24: rgba(5, 5, 6, 0.24);
|
|
14
|
+
--gl-color-alpha-dark-40: rgba(5, 5, 6, 0.4);
|
|
15
15
|
--gl-color-alpha-light-2: rgba(255, 255, 255, 0.02);
|
|
16
16
|
--gl-color-alpha-light-4: rgba(255, 255, 255, 0.04);
|
|
17
17
|
--gl-color-alpha-light-6: rgba(255, 255, 255, 0.06);
|
|
@@ -316,13 +316,13 @@
|
|
|
316
316
|
--gl-zindex-4: 4;
|
|
317
317
|
--gl-zindex-200: 200;
|
|
318
318
|
--gl-zindex-9999: 9999;
|
|
319
|
-
--gl-avatar-fallback-background-color-red:
|
|
320
|
-
--gl-avatar-fallback-background-color-purple:
|
|
321
|
-
--gl-avatar-fallback-background-color-blue:
|
|
322
|
-
--gl-avatar-fallback-background-color-green:
|
|
323
|
-
--gl-avatar-fallback-background-color-orange:
|
|
324
|
-
--gl-avatar-fallback-background-color-neutral:
|
|
325
|
-
--gl-chart-threshold-area-color: rgba(221,43,14,0.1); /** Used in charts to delineate a threshold area in a chart. */
|
|
319
|
+
--gl-avatar-fallback-background-color-red: rgba(252, 181, 170, 0.23921568627450981); /** Red background for avatar fallback with no particular meaning. */
|
|
320
|
+
--gl-avatar-fallback-background-color-purple: rgba(203, 187, 242, 0.23921568627450981); /** Purple background for avatar fallback with no particular meaning. */
|
|
321
|
+
--gl-avatar-fallback-background-color-blue: rgba(157, 199, 241, 0.23921568627450981); /** Blue background for avatar fallback with no particular meaning. */
|
|
322
|
+
--gl-avatar-fallback-background-color-green: rgba(145, 212, 168, 0.23921568627450981); /** Green background for avatar fallback with no particular meaning. */
|
|
323
|
+
--gl-avatar-fallback-background-color-orange: rgba(233, 190, 116, 0.23921568627450981); /** Orange background for avatar fallback with no particular meaning. */
|
|
324
|
+
--gl-avatar-fallback-background-color-neutral: rgba(191, 191, 195, 0.23921568627450981); /** Neutral background for avatar fallback with no particular meaning. */
|
|
325
|
+
--gl-chart-threshold-area-color: rgba(221, 43, 14, 0.1); /** Used in charts to delineate a threshold area in a chart. */
|
|
326
326
|
--gl-illustration-stroke-color-default: #171321; /** Default stroke color to define shape and provide essential detail. */
|
|
327
327
|
--gl-illustration-stroke-width-default: 2; /** Default stroke width to define shape and provide essential detail. */
|
|
328
328
|
--gl-illustration-fill-color-default: #fff; /** Default fill color for an element where specific meaning or emphasis is not required. */
|
|
@@ -562,12 +562,12 @@
|
|
|
562
562
|
--brand-gray-03: #74717a; /** Use color.brand-gray.03 instead. */
|
|
563
563
|
--brand-gray-04: #45424d; /** Use color.brand-gray.04 instead. */
|
|
564
564
|
--brand-gray-05: #2b2838; /** Use color.brand-gray.05 instead. */
|
|
565
|
-
--t-gray-a-16: rgba(
|
|
566
|
-
--t-gray-a-24: rgba(
|
|
567
|
-
--t-gray-a-02: rgba(
|
|
568
|
-
--t-gray-a-04: rgba(
|
|
569
|
-
--t-gray-a-06: rgba(
|
|
570
|
-
--t-gray-a-08: rgba(
|
|
565
|
+
--t-gray-a-16: rgba(5, 5, 6, 0.16); /** Use color.alpha.dark.16 instead. */
|
|
566
|
+
--t-gray-a-24: rgba(5, 5, 6, 0.24); /** Use color.alpha.dark.24 instead. */
|
|
567
|
+
--t-gray-a-02: rgba(5, 5, 6, 0.02); /** Use color.alpha.dark.2 instead. */
|
|
568
|
+
--t-gray-a-04: rgba(5, 5, 6, 0.04); /** Use color.alpha.dark.4 instead. */
|
|
569
|
+
--t-gray-a-06: rgba(5, 5, 6, 0.06); /** Use color.alpha.dark.6 instead. */
|
|
570
|
+
--t-gray-a-08: rgba(5, 5, 6, 0.08); /** Use color.alpha.dark.8 instead. */
|
|
571
571
|
--t-white-a-16: rgba(255, 255, 255, 0.16); /** Use color.alpha.light.16 instead. */
|
|
572
572
|
--t-white-a-24: rgba(255, 255, 255, 0.24); /** Use color.alpha.light.24 instead. */
|
|
573
573
|
--t-white-a-36: rgba(255, 255, 255, 0.36); /** Use color.alpha.light.36 instead. */
|
|
@@ -575,13 +575,13 @@
|
|
|
575
575
|
--t-white-a-04: rgba(255, 255, 255, 0.04); /** Use color.alpha.light.4 instead. */
|
|
576
576
|
--t-white-a-06: rgba(255, 255, 255, 0.06); /** Use color.alpha.light.6 instead. */
|
|
577
577
|
--t-white-a-08: rgba(255, 255, 255, 0.08); /** Use color.alpha.light.8 instead. */
|
|
578
|
-
--gl-action-neutral-background-color-default: rgba(164, 163, 168, 0
|
|
578
|
+
--gl-action-neutral-background-color-default: rgba(164, 163, 168, 0); /** Used for the background of a neutral action in the default state. */
|
|
579
579
|
--gl-action-neutral-background-color-hover: rgba(164, 163, 168, 0.16); /** Used for the background of a neutral action in the hover state. */
|
|
580
580
|
--gl-action-neutral-background-color-active: rgba(83, 81, 88, 0.24); /** Used for the background of a neutral action in the active state. */
|
|
581
|
-
--gl-action-confirm-background-color-default: rgba(99, 166, 233, 0
|
|
581
|
+
--gl-action-confirm-background-color-default: rgba(99, 166, 233, 0); /** Used for the background of a confirm (positive) action in the default state. */
|
|
582
582
|
--gl-action-confirm-background-color-hover: rgba(99, 166, 233, 0.16); /** Used for the background of a confirm (positive) action in the hover state. */
|
|
583
583
|
--gl-action-confirm-background-color-active: rgba(11, 92, 173, 0.24); /** Used for the background of a confirm (positive) action in the active state. */
|
|
584
|
-
--gl-action-danger-background-color-default: rgba(245, 127, 108, 0
|
|
584
|
+
--gl-action-danger-background-color-default: rgba(245, 127, 108, 0); /** Used for the background of a danger (destructive) action in the default state. */
|
|
585
585
|
--gl-action-danger-background-color-hover: rgba(245, 127, 108, 0.16); /** Used for the background of a danger (destructive) action in the hover state. */
|
|
586
586
|
--gl-action-danger-background-color-active: rgba(174, 24, 0, 0.24); /** Used for the background of a danger (destructive) action in the active state. */
|
|
587
587
|
--gl-letter-spacing-heading: -0.01em;
|