@sit-onyx/headless 1.0.0-beta.5 → 1.0.0-beta.6
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/package.json
CHANGED
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
type ListboxValue,
|
|
11
11
|
} from "../listbox/createListbox";
|
|
12
12
|
|
|
13
|
+
/** See https://w3c.github.io/aria/#aria-autocomplete */
|
|
13
14
|
export type ComboboxAutoComplete = "none" | "list" | "both";
|
|
14
15
|
|
|
15
16
|
export const OPENING_KEYS: PressedKey[] = ["ArrowDown", "ArrowUp", " ", "Enter", "Home", "End"];
|
|
@@ -19,11 +20,15 @@ export const CLOSING_KEYS: PressedKey[] = [
|
|
|
19
20
|
"Enter",
|
|
20
21
|
"Tab",
|
|
21
22
|
];
|
|
22
|
-
const SELECTING_KEYS_SINGLE: PressedKey[] = ["Enter", " "];
|
|
23
|
-
const SELECTING_KEYS_MULTIPLE: PressedKey[] = ["Enter"];
|
|
24
23
|
|
|
25
|
-
const
|
|
26
|
-
|
|
24
|
+
const SELECTING_KEYS: PressedKey[] = ["Enter"];
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* if the a search input is included, space should not be used to select
|
|
28
|
+
* TODO: idea for the future: move this distinction to the listbox?
|
|
29
|
+
*/
|
|
30
|
+
const isSelectingKey = (event: KeyboardEvent, withSpace?: boolean) => {
|
|
31
|
+
const selectingKeys = withSpace ? [...SELECTING_KEYS, " "] : SELECTING_KEYS;
|
|
27
32
|
return isKeyOfGroup(event, selectingKeys);
|
|
28
33
|
};
|
|
29
34
|
|
|
@@ -41,6 +46,10 @@ export type CreateComboboxOptions<
|
|
|
41
46
|
* Labels the listbox which displays the available options. E.g. the list label could be "Countries" for a combobox which is labelled "Country".
|
|
42
47
|
*/
|
|
43
48
|
listLabel: MaybeRef<string>;
|
|
49
|
+
/**
|
|
50
|
+
* Provides additional description for the listbox which displays the available options.
|
|
51
|
+
*/
|
|
52
|
+
listDescription?: MaybeRef<string | undefined>;
|
|
44
53
|
/**
|
|
45
54
|
* Controls the opened/visible state of the associated pop-up. When expanded the activeOption can be controlled via the keyboard.
|
|
46
55
|
*/
|
|
@@ -107,6 +116,7 @@ export const createComboBox = createBuilder(
|
|
|
107
116
|
multiple: multipleRef,
|
|
108
117
|
label,
|
|
109
118
|
listLabel,
|
|
119
|
+
listDescription,
|
|
110
120
|
isExpanded: isExpandedRef,
|
|
111
121
|
activeOption,
|
|
112
122
|
onToggle,
|
|
@@ -183,7 +193,7 @@ export const createComboBox = createBuilder(
|
|
|
183
193
|
}
|
|
184
194
|
return onActivateFirst?.();
|
|
185
195
|
}
|
|
186
|
-
if (isSelectingKey(event,
|
|
196
|
+
if (isSelectingKey(event, autocomplete.value === "none")) {
|
|
187
197
|
return handleSelect(activeOption.value!);
|
|
188
198
|
}
|
|
189
199
|
if (isExpanded.value && isKeyOfGroup(event, CLOSING_KEYS)) {
|
|
@@ -213,9 +223,11 @@ export const createComboBox = createBuilder(
|
|
|
213
223
|
internals: { getOptionId },
|
|
214
224
|
} = createListbox({
|
|
215
225
|
label: listLabel,
|
|
226
|
+
description: listDescription,
|
|
216
227
|
multiple,
|
|
217
228
|
controlled: true,
|
|
218
229
|
activeOption,
|
|
230
|
+
isExpanded,
|
|
219
231
|
onSelect: handleSelect,
|
|
220
232
|
});
|
|
221
233
|
|
|
@@ -30,7 +30,9 @@ const {
|
|
|
30
30
|
elements: { listbox, option: headlessOption },
|
|
31
31
|
} = createListbox({
|
|
32
32
|
label: "Test listbox",
|
|
33
|
+
description: "Test description",
|
|
33
34
|
activeOption,
|
|
35
|
+
isExpanded: true,
|
|
34
36
|
onSelect: (id) => {
|
|
35
37
|
selectedOption.value = selectedOption.value === id ? undefined : id;
|
|
36
38
|
},
|
|
@@ -10,6 +10,10 @@ export type CreateListboxOptions<TValue extends ListboxValue, TMultiple extends
|
|
|
10
10
|
* Aria label for the listbox.
|
|
11
11
|
*/
|
|
12
12
|
label: MaybeRef<string>;
|
|
13
|
+
/**
|
|
14
|
+
* Aria description for the listbox.
|
|
15
|
+
*/
|
|
16
|
+
description?: MaybeRef<string | undefined>;
|
|
13
17
|
/**
|
|
14
18
|
* Value of currently (visually) active option.
|
|
15
19
|
*/
|
|
@@ -19,6 +23,10 @@ export type CreateListboxOptions<TValue extends ListboxValue, TMultiple extends
|
|
|
19
23
|
* This disables keyboard events and makes the listbox not focusable.
|
|
20
24
|
*/
|
|
21
25
|
controlled?: boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Controls the opened/visible state of the listbox. When expanded the activeOption can be controlled via the keyboard.
|
|
28
|
+
*/
|
|
29
|
+
isExpanded?: MaybeRef<boolean>;
|
|
22
30
|
/**
|
|
23
31
|
* Whether the listbox is multiselect.
|
|
24
32
|
*/
|
|
@@ -77,6 +85,7 @@ export const createListbox = createBuilder(
|
|
|
77
85
|
options: CreateListboxOptions<TValue, TMultiple>,
|
|
78
86
|
) => {
|
|
79
87
|
const isMultiselect = computed(() => unref(options.multiple) ?? false);
|
|
88
|
+
const isExpanded = computed(() => unref(options.isExpanded) ?? false);
|
|
80
89
|
|
|
81
90
|
/**
|
|
82
91
|
* Map for option IDs. key = option value, key = ID for the HTML element
|
|
@@ -97,7 +106,11 @@ export const createListbox = createBuilder(
|
|
|
97
106
|
|
|
98
107
|
// scroll currently active option into view if needed
|
|
99
108
|
watchEffect(() => {
|
|
100
|
-
if (
|
|
109
|
+
if (
|
|
110
|
+
!isExpanded.value ||
|
|
111
|
+
options.activeOption.value == undefined ||
|
|
112
|
+
(!isFocused.value && !options.controlled)
|
|
113
|
+
)
|
|
101
114
|
return;
|
|
102
115
|
const id = getOptionId(options.activeOption.value);
|
|
103
116
|
document.getElementById(id)?.scrollIntoView({ block: "nearest", inline: "nearest" });
|
|
@@ -158,12 +171,14 @@ export const createListbox = createBuilder(
|
|
|
158
171
|
role: "listbox",
|
|
159
172
|
"aria-multiselectable": isMultiselect.value,
|
|
160
173
|
"aria-label": unref(options.label),
|
|
174
|
+
"aria-description": options.description,
|
|
161
175
|
tabindex: "-1",
|
|
162
176
|
}
|
|
163
177
|
: {
|
|
164
178
|
role: "listbox",
|
|
165
179
|
"aria-multiselectable": isMultiselect.value,
|
|
166
180
|
"aria-label": unref(options.label),
|
|
181
|
+
"aria-description": options.description,
|
|
167
182
|
tabindex: "0",
|
|
168
183
|
"aria-activedescendant":
|
|
169
184
|
options.activeOption.value != undefined
|
package/src/utils/vitest.ts
CHANGED