Skip to content

Commit

Permalink
next: add closeOnSelect prop to menu items (#859)
Browse files Browse the repository at this point in the history
  • Loading branch information
huntabyte authored Nov 3, 2024
1 parent dff1ed6 commit 8870e71
Show file tree
Hide file tree
Showing 7 changed files with 43 additions and 1 deletion.
5 changes: 5 additions & 0 deletions .changeset/rare-waves-lick.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"bits-ui": patch
---

add `closeOnSelect` prop to all the menu item components
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
disabled = false,
onSelect = noop,
controlledChecked = false,
closeOnSelect = true,
...restProps
}: MenuCheckboxItemProps = $props();
Expand All @@ -37,6 +38,7 @@
() => ref,
(v) => (ref = v)
),
closeOnSelect: box.with(() => closeOnSelect),
});
function handleSelect(e: Event) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
id = useId(),
disabled = false,
onSelect = noop,
closeOnSelect = true,
...restProps
}: MenuItemProps = $props();
Expand All @@ -23,6 +24,7 @@
() => ref,
(v) => (ref = v)
),
closeOnSelect: box.with(() => closeOnSelect),
});
const mergedProps = $derived(mergeProps(restProps, itemState.props));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
onSelect = noop,
id = useId(),
disabled = false,
closeOnSelect = true,
...restProps
}: MenuRadioItemProps = $props();
Expand All @@ -25,6 +26,7 @@
() => ref,
(v) => (ref = v)
),
closeOnSelect: box.with(() => closeOnSelect),
});
function handleSelect(e: Event) {
Expand Down
10 changes: 9 additions & 1 deletion packages/bits-ui/src/lib/bits/menu/menu.svelte.ts
Original file line number Diff line number Diff line change
Expand Up @@ -453,18 +453,21 @@ class MenuItemSharedState {

type MenuItemStateProps = ReadableBoxedValues<{
onSelect: AnyFn;
closeOnSelect: boolean;
}>;

class MenuItemState {
#item: MenuItemSharedState;
#onSelect: MenuItemStateProps["onSelect"];
#closeOnSelect: MenuItemStateProps["closeOnSelect"];
#isPointerDown = $state(false);
root: MenuRootState;

constructor(props: MenuItemStateProps, item: MenuItemSharedState) {
this.#item = item;
this.root = item.content.parentMenu.root;
this.#onSelect = props.onSelect;
this.#closeOnSelect = props.closeOnSelect;
}

#onkeydown = (e: KeyboardEvent) => {
Expand All @@ -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();
}
};
Expand Down Expand Up @@ -830,6 +835,7 @@ class MenuRadioGroupState {
type MenuRadioItemStateProps = ReadableBoxedValues<{
value: string;
id: string;
closeOnSelect: boolean;
}> &
WritableBoxedValues<{
ref: HTMLElement | null;
Expand All @@ -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;
Expand All @@ -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,
Expand Down
19 changes: 19 additions & 0 deletions packages/bits-ui/src/lib/bits/menu/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,12 @@ export type MenuItemPropsWithoutHTML<U extends Record<PropertyKey, unknown> = {
* 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
>;
Expand Down Expand Up @@ -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 &
Expand Down Expand Up @@ -250,6 +263,12 @@ export type MenuRadioItemPropsWithoutHTML = MenuItemPropsWithoutHTML<MenuRadioIt
* The value of the radio item.
*/
value: string;

/**
* Whether or not the menu item should close when selected.
* @defaultValue true
*/
closeOnSelect?: boolean;
};

export type MenuRadioItemProps = MenuRadioItemPropsWithoutHTML &
Expand Down
4 changes: 4 additions & 0 deletions sites/docs/src/lib/content/api-reference/menu.api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@ const sharedItemProps = {
definition: NoopProp,
description: "A callback that is fired when the menu item is selected.",
}),
closeOnSelect: createBooleanProp({
default: C.TRUE,
description: "Whether or not the menu item should close when selected.",
}),
...withChildProps({ elType: "HTMLDivElement" }),
} as const;

Expand Down

0 comments on commit 8870e71

Please sign in to comment.