fix(multi-select): address a11y issues

#2172
This commit is contained in:
Eric Liu 2025-08-17 13:40:22 -07:00
commit 28a895e3cc
2 changed files with 141 additions and 135 deletions

View file

@ -347,6 +347,22 @@
class="bx--list-box__invalid-icon bx--list-box__invalid-icon--warning"
/>
{/if}
<div class:bx--list-box__field--wrapper={true}>
{#if checked.length > 0}
<ListBoxSelection
selectionCount={checked.length}
on:clear
on:clear={() => {
selectedIds = [];
sortedItems = sortedItems.map((item) => ({
...item,
checked: false,
}));
}}
translateWithId={translateWithIdSelection}
{disabled}
/>
{/if}
<ListBoxField
role="button"
tabindex="0"
@ -404,21 +420,6 @@
{disabled}
{translateWithId}
>
{#if checked.length > 0}
<ListBoxSelection
selectionCount={checked.length}
on:clear
on:clear={() => {
selectedIds = [];
sortedItems = sortedItems.map((item) => ({
...item,
checked: false,
}));
}}
translateWithId={translateWithIdSelection}
{disabled}
/>
{/if}
{#if filterable}
<input
bind:this={inputRef}
@ -498,6 +499,7 @@
<ListBoxMenuIcon {open} {translateWithId} />
{/if}
</ListBoxField>
</div>
<div style:display={open ? "block" : "none"}>
<ListBoxMenu aria-label={ariaLabel} {id} aria-multiselectable="true">
{#each filterable ? filteredItems : sortedItems as item, i (item.id)}

View file

@ -465,20 +465,24 @@ describe("MultiSelect", () => {
selectedIds: ["0", "1"],
},
});
await user.click(screen.getAllByRole("button")[0]);
await openMenu();
const options = screen.getAllByRole("option");
expect(options[0]).toHaveAttribute("aria-selected", "true");
expect(options[1]).toHaveAttribute("aria-selected", "true");
expect(options[2]).toHaveAttribute("aria-selected", "false");
const clearButton = screen.getByRole("button", { name: /clear/i });
await closeMenu();
const clearButton = screen.getByRole("button", {
name: /clear all selected items/i,
});
await user.click(clearButton);
await user.click(screen.getByRole("button"));
expect(options[0]).toHaveAttribute("aria-selected", "false");
expect(options[1]).toHaveAttribute("aria-selected", "false");
expect(options[2]).toHaveAttribute("aria-selected", "false");
await openMenu();
const updatedOptions = screen.getAllByRole("option");
expect(updatedOptions[0]).toHaveAttribute("aria-selected", "false");
expect(updatedOptions[1]).toHaveAttribute("aria-selected", "false");
expect(updatedOptions[2]).toHaveAttribute("aria-selected", "false");
});
it("skips disabled items during keyboard navigation", async () => {