Menu
A list of options that appears when a user interacts with a button.
You can explore the menu component in the following curated examples.
Menu with Combobox
Create a searchable dropdown menu by combining Menu and Combobox.
Nested Menu
Render a nested menu with submenus.
Menu with Links
Render a Menu with links as the Menu Items.
Anatomy
<Menu.Root>
<Menu.Trigger>
<Menu.Indicator />
</Menu.Trigger>
<Menu.Positioner>
<Menu.Content>
<Menu.Arrow>
<Menu.ArrowTip />
</Menu.Arrow>
<Menu.Item />
<Menu.ItemGroup>
<Menu.ItemGroupLabel />
<Menu.Item />
</Menu.ItemGroup>
<Menu.Separator />
</Menu.Content>
</Menu.Positioner>
</Menu.Root>
Examples
Item Selection
Use onSelect to handle item selection. The callback receives the item's id.
Root Provider
An alternative way to control the menu is to use the RootProvider component and the useMenu hook. This way you can
access the state and methods from outside the component.
Grouping
Use Menu.ItemGroup and Menu.ItemGroupLabel to organize related menu items.
Links
To render menu items as links, use the asChild prop to replace the default element with an anchor tag.
Checkbox
To add a checkbox to a menu item, use the Menu.Checkbox component.
Radio Group
To group radio option items, use the Menu.RadioGroup component.
Context Menu
To show the menu when a trigger element is right-clicked, use the Menu.ContextTrigger component.
Context menus are also opened during a long-press of roughly 700ms when the pointer is pen or touch.
Nested
To show a nested menu, render another Menu component and use the Menu.TriggerItem component to open the submenu.
Menu in Dialog
When rendering a menu inside a dialog, use lazyMount and unmountOnExit to ensure proper cleanup when the dialog
closes.
Menu Item Dialog
Open a confirmation dialog from a menu item. This pattern is useful for destructive actions like delete that require user confirmation.
Guides
Custom IDs
Ark UI autogenerates ids for menu items internally. Passing a custom id prop breaks the internal getElementById
functionality used by the component.
// ❌ Don't do this
<Menu.Item id="custom-id" value="custom-value">
Custom Item
</Menu.Item>
// ✅ Do this
<Menu.Item value="custom-value">
Custom Item
</Menu.Item>
Links
To render a menu item as a link, render the link as the menu item itself using the asChild prop, not as a child of the
menu item.
This pattern ensures the link element receives the correct ARIA attributes and keyboard interactions from the menu item.
Here's an example of a reusable MenuItemLink component:
interface MenuItemLinkProps extends Menu.ItemProps {
href?: string
target?: string
}
export const MenuItemLink = (props: MenuItemLinkProps) => {
const { href, target, children, ...rest } = props
return (
<Menu.Item {...rest} asChild>
<a href={href} target={target}>
{children}
</a>
</Menu.Item>
)
}
API Reference
Props
Root
| Prop | Default | Type |
|---|---|---|
anchorPoint | PointThe positioning point for the menu. Can be set by the context menu trigger or the button trigger. | |
aria-label | stringThe accessibility label for the menu | |
closeOnSelect | true | booleanWhether to close the menu when an option is selected |
composite | true | booleanWhether the menu is a composed with other composite widgets like a combobox or tabs |
defaultHighlightedValue | stringThe initial highlighted value of the menu item when rendered. Use when you don't need to control the highlighted value of the menu item. | |
defaultOpen | booleanThe initial open state of the menu when rendered. Use when you don't need to control the open state of the menu. | |
highlightedValue | stringThe controlled highlighted value of the menu item. | |
id | stringThe unique identifier of the machine. | |
ids | Partial<{
trigger: string
contextTrigger: string
content: string
groupLabel: (id: string) => string
group: (id: string) => string
positioner: string
arrow: string
}>The ids of the elements in the menu. Useful for composition. | |
immediate | booleanWhether to synchronize the present change immediately or defer it to the next frame | |
lazyMount | false | booleanWhether to enable lazy mounting |
loopFocus | false | booleanWhether to loop the keyboard navigation. |
navigate | (details: NavigateDetails) => voidFunction to navigate to the selected item if it's an anchor element | |
onEscapeKeyDown | (event: KeyboardEvent) => voidFunction called when the escape key is pressed | |
onExitComplete | VoidFunctionFunction called when the animation ends in the closed state | |
onFocusOutside | (event: FocusOutsideEvent) => voidFunction called when the focus is moved outside the component | |
onHighlightChange | (details: HighlightChangeDetails) => voidFunction called when the highlighted menu item changes. | |
onInteractOutside | (event: InteractOutsideEvent) => voidFunction called when an interaction happens outside the component | |
onOpenChange | (details: OpenChangeDetails) => voidFunction called when the menu opens or closes | |
onPointerDownOutside | (event: PointerDownOutsideEvent) => voidFunction called when the pointer is pressed down outside the component | |
onRequestDismiss | (event: LayerDismissEvent) => voidFunction called when this layer is closed due to a parent layer being closed | |
onSelect | (details: SelectionDetails) => voidFunction called when a menu item is selected. | |
open | booleanThe controlled open state of the menu | |
positioning | PositioningOptionsThe options used to dynamically position the menu | |
present | booleanWhether the node is present (controlled by the user) | |
skipAnimationOnMount | false | booleanWhether to allow the initial presence animation. |
typeahead | true | booleanWhether the pressing printable characters should trigger typeahead navigation |
unmountOnExit | false | booleanWhether to unmount on exit. |
Arrow
Renders a <div> element.
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
| CSS Variable | Description |
|---|---|
--arrow-size | The size of the arrow |
--arrow-size-half | Half the size of the arrow |
--arrow-background | Use this variable to style the arrow background |
--arrow-offset | The offset position of the arrow |
ArrowTip
Renders a <div> element.
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
CheckboxItem
Renders a <div> element.
| Prop | Default | Type |
|---|---|---|
checked | booleanWhether the option is checked | |
value | stringThe value of the option | |
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. | |
closeOnSelect | booleanWhether the menu should be closed when the option is selected. | |
disabled | booleanWhether the menu item is disabled | |
onCheckedChange | (checked: boolean) => voidFunction called when the option state is changed | |
valueText | stringThe textual value of the option. Used in typeahead navigation of the menu. If not provided, the text content of the menu item will be used. |
Content
Renders a <div> element.
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
| Attribute | Description |
|---|---|
[data-scope] | menu |
[data-part] | content |
[data-state] | "open" | "closed" |
[data-nested] | menu |
[data-has-nested] | menu |
[data-placement] | The placement of the content |
| CSS Variable | Description |
|---|---|
--layer-index | The index of the dismissable in the layer stack |
--nested-layer-count | The number of nested menus |
ContextTrigger
Renders a <button> element.
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
| Attribute | Description |
|---|---|
[data-scope] | menu |
[data-part] | context-trigger |
[data-state] | "open" | "closed" |
Indicator
Renders a <div> element.
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
| Attribute | Description |
|---|---|
[data-scope] | menu |
[data-part] | indicator |
[data-state] | "open" | "closed" |
ItemGroupLabel
Renders a <div> element.
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
ItemGroup
Renders a <div> element.
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
ItemIndicator
Renders a <div> element.
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
| Attribute | Description |
|---|---|
[data-scope] | menu |
[data-part] | item-indicator |
[data-disabled] | Present when disabled |
[data-highlighted] | Present when highlighted |
[data-state] | "checked" |
Item
Renders a <div> element.
| Prop | Default | Type |
|---|---|---|
value | stringThe unique value of the menu item option. | |
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. | |
closeOnSelect | booleanWhether the menu should be closed when the option is selected. | |
disabled | booleanWhether the menu item is disabled | |
onSelect | VoidFunctionThe function to call when the item is selected | |
valueText | stringThe textual value of the option. Used in typeahead navigation of the menu. If not provided, the text content of the menu item will be used. |
| Attribute | Description |
|---|---|
[data-scope] | menu |
[data-part] | item |
[data-disabled] | Present when disabled |
[data-highlighted] | Present when highlighted |
[data-value] | The value of the item |
[data-valuetext] | The human-readable value |
ItemText
Renders a <div> element.
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
| Attribute | Description |
|---|---|
[data-scope] | menu |
[data-part] | item-text |
[data-disabled] | Present when disabled |
[data-highlighted] | Present when highlighted |
[data-state] | "checked" |
Positioner
Renders a <div> element.
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
| CSS Variable | Description |
|---|---|
--reference-width | The width of the reference element |
--reference-height | The height of the root |
--available-width | The available width in viewport |
--available-height | The available height in viewport |
--x | The x position for transform |
--y | The y position for transform |
--z-index | The z-index value |
--transform-origin | The transform origin for animations |
RadioItemGroup
Renders a <div> element.
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. | |
onValueChange | (e: ValueChangeDetails) => void | |
value | string |
RadioItem
Renders a <div> element.
| Prop | Default | Type |
|---|---|---|
value | stringThe value of the option | |
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. | |
closeOnSelect | booleanWhether the menu should be closed when the option is selected. | |
disabled | booleanWhether the menu item is disabled | |
valueText | stringThe textual value of the option. Used in typeahead navigation of the menu. If not provided, the text content of the menu item will be used. |
RootProvider
| Prop | Default | Type |
|---|---|---|
value | UseMenuReturn | |
immediate | booleanWhether to synchronize the present change immediately or defer it to the next frame | |
lazyMount | false | booleanWhether to enable lazy mounting |
onExitComplete | VoidFunctionFunction called when the animation ends in the closed state | |
present | booleanWhether the node is present (controlled by the user) | |
skipAnimationOnMount | false | booleanWhether to allow the initial presence animation. |
unmountOnExit | false | booleanWhether to unmount on exit. |
Separator
Renders a <hr> element.
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
TriggerItem
Renders a <div> element.
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
Trigger
Renders a <button> element.
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
| Attribute | Description |
|---|---|
[data-scope] | menu |
[data-part] | trigger |
[data-placement] | The placement of the trigger |
[data-state] | "open" | "closed" |
Context
API
| Property | Type |
|---|---|
open | booleanWhether the menu is open |
setOpen | (open: boolean) => voidFunction to open or close the menu |
highlightedValue | stringThe id of the currently highlighted menuitem |
setHighlightedValue | (value: string) => voidFunction to set the highlighted menuitem |
setParent | (parent: ParentMenuService) => voidFunction to register a parent menu. This is used for submenus |
setChild | (child: ChildMenuService) => voidFunction to register a child menu. This is used for submenus |
reposition | (options?: Partial<PositioningOptions>) => voidFunction to reposition the popover |
getOptionItemState | (props: OptionItemProps) => OptionItemStateReturns the state of the option item |
getItemState | (props: ItemProps) => ItemStateReturns the state of the menu item |
addItemListener | (props: ItemListenerProps) => VoidFunctionSetup the custom event listener for item selection event |
Accessibility
Complies with the Menu WAI-ARIA design pattern.
Keyboard Support
| Key | Description |
|---|---|
Space | Activates/Selects the highlighted item |
Enter | Activates/Selects the highlighted item |
ArrowDown | Highlights the next item in the menu |
ArrowUp | Highlights the previous item in the menu |
ArrowRightArrowLeft | When focus is on trigger, opens or closes the submenu depending on reading direction. |
Esc | Closes the menu and moves focus to the trigger |