diff --git a/.changeset/rare-waves-lick.md b/.changeset/rare-waves-lick.md new file mode 100644 index 000000000..f06ba9b8b --- /dev/null +++ b/.changeset/rare-waves-lick.md @@ -0,0 +1,5 @@ +--- +"bits-ui": patch +--- + +add `closeOnSelect` prop to all the menu item components diff --git a/packages/bits-ui/src/lib/bits/menu/components/menu-checkbox-item.svelte b/packages/bits-ui/src/lib/bits/menu/components/menu-checkbox-item.svelte index c1a9af56a..d9f01d785 100644 --- a/packages/bits-ui/src/lib/bits/menu/components/menu-checkbox-item.svelte +++ b/packages/bits-ui/src/lib/bits/menu/components/menu-checkbox-item.svelte @@ -15,6 +15,7 @@ disabled = false, onSelect = noop, controlledChecked = false, + closeOnSelect = true, ...restProps }: MenuCheckboxItemProps = $props(); @@ -37,6 +38,7 @@ () => ref, (v) => (ref = v) ), + closeOnSelect: box.with(() => closeOnSelect), }); function handleSelect(e: Event) { diff --git a/packages/bits-ui/src/lib/bits/menu/components/menu-item.svelte b/packages/bits-ui/src/lib/bits/menu/components/menu-item.svelte index 18ff4ae0f..6ec3a1a5a 100644 --- a/packages/bits-ui/src/lib/bits/menu/components/menu-item.svelte +++ b/packages/bits-ui/src/lib/bits/menu/components/menu-item.svelte @@ -12,6 +12,7 @@ id = useId(), disabled = false, onSelect = noop, + closeOnSelect = true, ...restProps }: MenuItemProps = $props(); @@ -23,6 +24,7 @@ () => ref, (v) => (ref = v) ), + closeOnSelect: box.with(() => closeOnSelect), }); const mergedProps = $derived(mergeProps(restProps, itemState.props)); diff --git a/packages/bits-ui/src/lib/bits/menu/components/menu-radio-item.svelte b/packages/bits-ui/src/lib/bits/menu/components/menu-radio-item.svelte index ad47f895d..56d2726a2 100644 --- a/packages/bits-ui/src/lib/bits/menu/components/menu-radio-item.svelte +++ b/packages/bits-ui/src/lib/bits/menu/components/menu-radio-item.svelte @@ -13,6 +13,7 @@ onSelect = noop, id = useId(), disabled = false, + closeOnSelect = true, ...restProps }: MenuRadioItemProps = $props(); @@ -25,6 +26,7 @@ () => ref, (v) => (ref = v) ), + closeOnSelect: box.with(() => closeOnSelect), }); function handleSelect(e: Event) { diff --git a/packages/bits-ui/src/lib/bits/menu/menu.svelte.ts b/packages/bits-ui/src/lib/bits/menu/menu.svelte.ts index cdcebef0c..7e08f47ed 100644 --- a/packages/bits-ui/src/lib/bits/menu/menu.svelte.ts +++ b/packages/bits-ui/src/lib/bits/menu/menu.svelte.ts @@ -453,11 +453,13 @@ class MenuItemSharedState { type MenuItemStateProps = ReadableBoxedValues<{ onSelect: AnyFn; + closeOnSelect: boolean; }>; class MenuItemState { #item: MenuItemSharedState; #onSelect: MenuItemStateProps["onSelect"]; + #closeOnSelect: MenuItemStateProps["closeOnSelect"]; #isPointerDown = $state(false); root: MenuRootState; @@ -465,6 +467,7 @@ class MenuItemState { this.#item = item; this.root = item.content.parentMenu.root; this.#onSelect = props.onSelect; + this.#closeOnSelect = props.closeOnSelect; } #onkeydown = (e: KeyboardEvent) => { @@ -490,7 +493,9 @@ class MenuItemState { await tick(); if (selectEvent.defaultPrevented) { this.#item.content.parentMenu.root.isUsingKeyboard.current = false; - } else { + return; + } + if (this.#closeOnSelect.current) { this.#item.content.parentMenu.root.onClose(); } }; @@ -830,6 +835,7 @@ class MenuRadioGroupState { type MenuRadioItemStateProps = ReadableBoxedValues<{ value: string; id: string; + closeOnSelect: boolean; }> & WritableBoxedValues<{ ref: HTMLElement | null; @@ -838,6 +844,7 @@ type MenuRadioItemStateProps = ReadableBoxedValues<{ class MenuRadioItemState { #id: MenuRadioItemStateProps["id"]; #ref: MenuRadioItemStateProps["ref"]; + #closeOnSelect: MenuRadioItemStateProps["closeOnSelect"]; #item: MenuItemState; #value: MenuRadioItemStateProps["value"]; #group: MenuRadioGroupState; @@ -849,6 +856,7 @@ class MenuRadioItemState { this.#ref = props.ref; this.#group = group; this.#value = props.value; + this.#closeOnSelect = props.closeOnSelect; useRefById({ id: this.#id, diff --git a/packages/bits-ui/src/lib/bits/menu/types.ts b/packages/bits-ui/src/lib/bits/menu/types.ts index 20353d5e6..b3350cdc6 100644 --- a/packages/bits-ui/src/lib/bits/menu/types.ts +++ b/packages/bits-ui/src/lib/bits/menu/types.ts @@ -107,6 +107,12 @@ export type MenuItemPropsWithoutHTML = { * Prevent default behavior of selection with `event.preventDefault()`. */ onSelect?: (event: Event) => void; + + /** + * Whether or not the menu item should close when selected. + * @defaultValue true + */ + closeOnSelect?: boolean; }, U >; @@ -139,6 +145,13 @@ export type MenuCheckboxItemPropsWithoutHTML = * @defaultValue false */ controlledChecked?: boolean; + + /** + * Whether or not the menu item should close when selected. + * + * @defaultValue true + */ + closeOnSelect?: boolean; }; export type MenuCheckboxItemProps = MenuCheckboxItemPropsWithoutHTML & @@ -250,6 +263,12 @@ export type MenuRadioItemPropsWithoutHTML = MenuItemPropsWithoutHTML