Skip to content

Commit 5b60acb

Browse files
authored
feat(Menu): expose openDelay prop on *Menu.SubTrigger (#1845)
1 parent 5b75166 commit 5b60acb

File tree

5 files changed

+34
-4
lines changed

5 files changed

+34
-4
lines changed

.changeset/public-humans-behave.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"bits-ui": minor
3+
---
4+
5+
feat(Menu): expose `openDelay` prop on `*Menu.SubTrigger` to control open delay

docs/src/lib/content/api-reference/menu.api.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ import {
5959
defineSimpleDataAttr,
6060
defineStringProp,
6161
defineSimplePropSchema,
62+
defineNumberProp,
6263
} from "../utils.js";
6364

6465
const sharedItemProps = {
@@ -242,6 +243,11 @@ const subTriggerProps = {
242243
default: false,
243244
description: "Whether or not the submenu trigger is disabled.",
244245
}),
246+
openDelay: defineNumberProp({
247+
default: 100,
248+
description:
249+
"The amount of time in ms from when the mouse enters the subtrigger until the submenu opens.",
250+
}),
245251
...omit(sharedItemProps, "closeOnSelect"),
246252
} satisfies PropObj<DropdownMenuSubTriggerPropsWithoutHTML>;
247253

packages/bits-ui/src/lib/bits/menu/components/menu-sub-trigger.svelte

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
children,
1616
child,
1717
onSelect = noop,
18+
openDelay = 100,
1819
...restProps
1920
}: MenuSubTriggerProps = $props();
2021
@@ -26,6 +27,7 @@
2627
() => ref,
2728
(v) => (ref = v)
2829
),
30+
openDelay: boxWith(() => openDelay),
2931
});
3032
3133
const mergedProps = $derived(mergeProps(restProps, subTriggerState.props));

packages/bits-ui/src/lib/bits/menu/menu.svelte.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
type WritableBoxedValues,
1010
simpleBox,
1111
boxWith,
12+
type ReadableBox,
1213
} from "svelte-toolbelt";
1314
import { Context, watch } from "runed";
1415
import {
@@ -609,7 +610,9 @@ export class MenuItemState {
609610

610611
interface MenuSubTriggerStateOpts
611612
extends MenuItemSharedStateOpts,
612-
Pick<MenuItemStateOpts, "onSelect"> {}
613+
Pick<MenuItemStateOpts, "onSelect"> {
614+
openDelay: ReadableBox<number>;
615+
}
613616

614617
export class MenuSubTriggerState {
615618
static create(opts: MenuSubTriggerStateOpts) {
@@ -664,7 +667,7 @@ export class MenuSubTriggerState {
664667
this.#openTimer = this.content.domContext.setTimeout(() => {
665668
this.submenu.onOpen();
666669
this.#clearOpenTimer();
667-
}, 100);
670+
}, this.opts.openDelay.current);
668671
}
669672
}
670673

packages/bits-ui/src/lib/bits/menu/types.ts

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -223,8 +223,22 @@ export type MenuSubContentStaticPropsWithoutHTML = Expand<
223223
export type MenuSubContentStaticProps = MenuSubContentStaticPropsWithoutHTML &
224224
Without<BitsPrimitiveDivAttributes, MenuSubContentStaticPropsWithoutHTML>;
225225

226-
export type MenuSubTriggerPropsWithoutHTML = Omit<MenuItemPropsWithoutHTML, "closeOnSelect">;
227-
export type MenuSubTriggerProps = Omit<MenuItemProps, "closeOnSelect">;
226+
export type MenuSubTriggerPropsWithoutHTML = Omit<MenuItemPropsWithoutHTML, "closeOnSelect"> & {
227+
/**
228+
* The amount of time in ms from when the mouse enters the subtrigger until
229+
* the submenu opens. This is useful for preventing the submenu from opening
230+
* as a user is moving their mouse through the menu without a true intention to open that
231+
* submenu.
232+
*
233+
* To disable the behavior, set it to `0`.
234+
*
235+
* @default 100
236+
*/
237+
openDelay?: number;
238+
};
239+
240+
export type MenuSubTriggerProps = MenuSubTriggerPropsWithoutHTML &
241+
Without<BitsPrimitiveDivAttributes, MenuSubTriggerPropsWithoutHTML>;
228242

229243
export type MenuSeparatorPropsWithoutHTML = WithChild;
230244
export type MenuSeparatorProps = MenuSeparatorPropsWithoutHTML &

0 commit comments

Comments
 (0)