From db021fc0ce8773cc1a4d946cf5f4ecca9e4dcd68 Mon Sep 17 00:00:00 2001 From: Hunter Johnston Date: Wed, 2 Oct 2024 18:05:48 -0400 Subject: [PATCH 1/2] next: gracefully handle deselect on single listbox --- .../src/lib/bits/listbox/components/listbox.svelte | 2 -- .../bits-ui/src/lib/bits/listbox/listbox.svelte.ts | 4 +++- packages/bits-ui/src/tests/listbox/listbox.test.ts | 13 +++++++++++++ 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/packages/bits-ui/src/lib/bits/listbox/components/listbox.svelte b/packages/bits-ui/src/lib/bits/listbox/components/listbox.svelte index 19cf340bc..4968315b1 100644 --- a/packages/bits-ui/src/lib/bits/listbox/components/listbox.svelte +++ b/packages/bits-ui/src/lib/bits/listbox/components/listbox.svelte @@ -31,8 +31,6 @@ } } - value === undefined && (value = type === "single" ? "" : []); - useListboxRoot({ type, value: box.with( diff --git a/packages/bits-ui/src/lib/bits/listbox/listbox.svelte.ts b/packages/bits-ui/src/lib/bits/listbox/listbox.svelte.ts index c794afb27..3c28d6336 100644 --- a/packages/bits-ui/src/lib/bits/listbox/listbox.svelte.ts +++ b/packages/bits-ui/src/lib/bits/listbox/listbox.svelte.ts @@ -800,8 +800,10 @@ class ListboxItemState { // prevent any default behavior e.preventDefault(); if (this.disabled.current) return; + const isCurrentSelectedValue = this.value.current === this.root.value.current; this.root.toggleItem(this.value.current, this.label.current); - if (!this.root.isMulti) { + + if (!this.root.isMulti && !isCurrentSelectedValue) { this.root.closeMenu(); } }; diff --git a/packages/bits-ui/src/tests/listbox/listbox.test.ts b/packages/bits-ui/src/tests/listbox/listbox.test.ts index 355e80881..97e7254fb 100644 --- a/packages/bits-ui/src/tests/listbox/listbox.test.ts +++ b/packages/bits-ui/src/tests/listbox/listbox.test.ts @@ -416,6 +416,19 @@ describe("listbox - single", () => { const content = getByTestId("content"); expect(content).toBeVisible(); }); + + it("should deselect the selected item when the user clicks on the selected item", async () => { + const { getByTestId, user, trigger } = await openSingle(); + const [item0] = getItems(getByTestId); + await user.click(item0!); + expectSelected(item0!); + await user.click(trigger); + + const [item0v2] = getItems(getByTestId); + + await user.click(item0v2!); + expectNotSelected(item0v2!); + }); }); //////////////////////////////////// From 9f7c41e1dd28b32e322be6bbbb31a5896fdc2377 Mon Sep 17 00:00:00 2001 From: Hunter Johnston <64506580+huntabyte@users.noreply.github.com> Date: Wed, 2 Oct 2024 18:07:42 -0400 Subject: [PATCH 2/2] add changeset --- .changeset/serious-shrimps-pump.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/serious-shrimps-pump.md diff --git a/.changeset/serious-shrimps-pump.md b/.changeset/serious-shrimps-pump.md new file mode 100644 index 000000000..d21c9e897 --- /dev/null +++ b/.changeset/serious-shrimps-pump.md @@ -0,0 +1,5 @@ +--- +"bits-ui": patch +--- + +Listbox/Combobox: gracefully handle deselect when `type="single"`