XiodUI
HomeDocs
OverviewComponentsStyling & CustomizationChangelog

Components

  • Accordion
  • Agent Steps
  • Alert
  • Alert Dialog
  • Aspect Ratio
  • Autocomplete
  • Avatar
  • Badge
  • Breadcrumb
  • Button
  • Button Group
  • Button Split
  • Calendar
  • Card
  • Carousel
  • Checkbox
  • Circular Progress
  • Collapsible
  • Color Picker
  • Combobox
  • Command
  • Context Menu
  • Copy To Clipboard
  • Corner Badge
  • Dashboard Grid
  • Date Picker
  • Dialog
  • Dot Matrix
  • Draggable
    Updated
  • Drawer
  • Empty
  • Field
  • Fieldset
  • File Upload
    Updated
  • Form
  • Frame
  • Gauge
  • Grid
  • Group
  • Input
  • Input Group
  • Input OTP
  • Input Payment
  • Input Phone
    Updated
  • Input Sensitive
  • Kbd
  • Kinetic Click
  • Label
  • List Box
    Updated
  • Loader
  • Marker
  • Menu
  • Menubar
  • Message
  • Meter
  • Morphic Toast
  • Navigation Menu
  • Number Field
  • Option Picker
  • Orb
  • Pagination
  • Popover
  • Preview Card
    Updated
  • Progress
  • Radio
  • Resizable
  • Ruler Picker
  • Scroll Area
  • Scroll Bar
  • Select
  • Separator
  • Sidebar
  • Skeleton
  • Slider
  • Sortable
  • Switch
  • Table
  • Tabs
  • Text
  • Textarea
  • Timeline
  • Toast
  • Toggle
  • Toggle Group
  • Toolbar
  • Tooltip
  • Waveform
  • Wheel Picker

Loading...

Preview Skeleton

Installation Skeleton

Usage Skeleton

API Reference Skeleton

Sponsors

Support the development of XiodUI and help us build the best component library on Earth.

+++
Sponsor on GitHub

Menu

Previous: MarkerNext: Menubar

A dropdown menu of actions, opened from a button.

Preview

Loading Preview...

Installation

bun add xiod-ui

Usage

Imports

1import {2  Menu,3  MenuArrow,4  MenuCheckboxItem,5  MenuGroup,6  MenuGroupLabel,7  MenuItem,8  MenuPopup,9  MenuPortal,10  MenuRadioGroup,11  MenuRadioItem,12  MenuSeparator,13  MenuShortcut,14  MenuSub,15  MenuSubPopup,16  MenuSubTrigger,17  MenuTrigger,18  MenuCreateHandle19} from "xiod-ui/menu";

Anatomy

1<Menu>2  <MenuTrigger />3  <MenuPopup>4    <MenuGroup>5      <MenuGroupLabel />6      <MenuItem>7        <MenuShortcut />8      </MenuItem>9    </MenuGroup>10    <MenuSeparator />11    <MenuCheckboxItem />12    <MenuSub>13      <MenuSubTrigger />14      <MenuSubPopup>15        <MenuItem />16      </MenuSubPopup>17    </MenuSub>18    <MenuItem>19      <MenuShortcut />20    </MenuItem>21  </MenuPopup>22</Menu>

API Reference

Detailed documentation of properties and options.

Menu

PropTypeDefaultDescription
actionsRef
RefObject<MenuRootActions | null>
–

A ref to imperative actions.

  • unmount: Ends the closing phase of the menu after an externally controlled closing animation finishes. Call preventUnmountOnClose() in onOpenChange first, otherwise the menu completes closing on its own. Whether it leaves the DOM is decided by keepMounted on the portal.
  • close
MarkerMenubar
: Closes the menu imperatively when called.
children
ReactNode | PayloadChildRenderFunction<Payload>
–

The content of the menu. This can be a regular React node or a render function that receives the payload of the active trigger.

closeParentOnEsc
boolean
false

When in a submenu, determines whether pressing the Escape key closes the entire menu, or only the current child menu.

defaultOpen
boolean
false

Whether the menu is initially open.

To render a controlled menu, use the open prop instead.

defaultTriggerId
string|null
–

ID of the trigger that the menu is associated with. This is useful in conjunction with the defaultOpen prop to create an initially open menu.

disabled
boolean
false

Whether the component should ignore user interaction.

handle
MenuHandle<Payload>
–

A handle to associate the menu with a trigger. If specified, allows external triggers to control the menu's open state.

highlightItemOnHover
boolean
true

Whether moving the pointer over items should highlight them. Disabling this prop allows CSS :hover to be differentiated from the :focus (data-highlighted) state.

loopFocus
boolean
true

Whether to loop keyboard focus back to the first item when the end of the list is reached while using the arrow keys.

modal
boolean
true

Determines if the menu enters a modal state when open.

  • true: user interaction is limited to the menu: document page scroll is locked and pointer interactions on outside elements are disabled.
  • false: user interaction with the rest of the document is allowed.

On touch devices, a true modal blocks outside taps but leaves the page scrollable unless the popup spans nearly the full viewport width, matching native iOS behavior.

Nested menus ignore this prop, and menus opened by hover are never modal.

onItemHighlighted
((highlightedItem: HTMLElement, eventDetails: MenuRootHighlightEventDetails) => void)
–

Callback fired when an item is highlighted or unhighlighted. Receives the highlighted item element (or undefined if no item is highlighted) and details containing the reason for the change, the event, and the item's text label. The reason can be:

  • 'keyboard': the highlight changed due to keyboard navigation.
  • 'pointer': the highlight changed due to pointer hovering. The event may be a MouseEvent rather than a PointerEvent.
  • 'none': the highlight changed for another reason, such as automatic highlighting while filtering, the item list changing, or the popup opening or closing.
onOpenChange
((open: boolean, eventDetails: MenuRootChangeEventDetails) => void)
–

Event handler called when the menu is opened or closed.

onOpenChangeComplete
((open: boolean) => void)
–

Event handler called after any animations complete when the menu is opened or closed.

open
boolean
–

Whether the menu is currently open.

orientation
"horizontal"|"vertical"
'vertical'

The visual orientation of the menu. Controls whether roving focus uses up/down or left/right arrow keys.

triggerId
string|null
–

ID of the trigger that the menu is associated with. This is useful in conjunction with the open prop to create a controlled menu. There's no need to specify this prop when the menu is uncontrolled (that is, when the open prop is not set).

MenuArrow

Accepts className, style and render, plus every native attribute of the element it renders.

MenuCheckboxItem

Accepts className, style and render, plus every native attribute of the element it renders.

PropTypeDefaultDescription
checked
boolean
–

Whether the checkbox item is currently ticked.

To render an uncontrolled checkbox item, use the defaultChecked prop instead.

closeOnClick
boolean
false

Whether to close the menu when the item is clicked.

defaultChecked
boolean
false

Whether the checkbox item is initially ticked.

To render a controlled checkbox item, use the checked prop instead.

disabled
boolean
false

Whether the component should ignore user interaction.

label
string
–

Overrides the text used for keyboard text navigation and filtering. Falls back to the rendered text when not provided.

nativeButton
boolean
false

Whether the component renders a native <button> element when replacing it via the render prop. Set to true if the rendered element is a native button.

onCheckedChange
((checked: boolean, eventDetails: MenuRootChangeEventDetails) => void)
–

Event handler called when the checkbox item is ticked or unticked.

onClick
((event: BaseUIEvent<MouseEvent<HTMLDivElement, MouseEvent>>) => void)
–

The click handler for the menu item.

variant
"switch"|"default"
default

The visual style of the component.

MenuGroup

Accepts className, style and render, plus every native attribute of the element it renders.

PropTypeDefaultDescription
children
ReactNode
–

The content of the component.

MenuGroupLabel

Accepts className, style and render, plus every native attribute of the element it renders.

PropTypeDefaultDescription
inset
boolean
–

Whether to indent the label so it lines up with items that have an icon.

MenuItem

Accepts className, style and render, plus every native attribute of the element it renders.

PropTypeDefaultDescription
closeOnClick
boolean
true

Whether to close the menu when the item is clicked.

disabled
boolean
false

Whether the component should ignore user interaction.

inset
boolean
–

Whether to indent the item so its text lines up with items that have an icon.

label
string
–

Overrides the text used for keyboard text navigation and filtering. Falls back to the rendered text when not provided.

nativeButton
boolean
false

Whether the component renders a native <button> element when replacing it via the render prop. Set to true if the rendered element is a native button.

onClick
((event: BaseUIEvent<MouseEvent<HTMLDivElement, MouseEvent>>) => void)
–

The click handler for the menu item.

variant
"default"|"destructive"
default

The visual style of the component.

MenuPopup

Accepts className, style and render, plus every native attribute of the element it renders.

PropTypeDefaultDescription
align
"center"|"start"|"end"
center

How the calendar lines up with the trigger along that side.

alignOffset
number|OffsetFunction
–

Additional offset along the alignment axis, in pixels.

anchor
Menu$1.Positioner.Props["anchor"]
–

An element to position the popup against. Defaults to the trigger.

children
ReactNode
–

The content of the component.

finalFocus
boolean | RefObject<HTMLElement | null> | ((closeType: InteractionType) => boolean | void | HTMLElement | null)
–

Determines the element to focus when the menu is closed.

  • false: Do not move focus.
  • true: Move focus based on the default behavior (trigger or previously focused element).
  • RefObject: Move focus to the ref element.
  • function: Called with the interaction type (mouse, touch, pen, or keyboard). Return an element to focus, true to use the default behavior, or false/undefined to do nothing.
hideArrow
boolean
false

Whether to hide the arrow that points at the trigger.

side
"top"|"bottom"|"left"|"right"|"inline-end"|"inline-start"
bottom

Which side of the copy button the tooltip and toast open on.

sideOffset
number|OffsetFunction
8

The gap between the trigger and the calendar, in pixels.

MenuPortal

Accepts className, style and render, plus every native attribute of the element it renders.

PropTypeDefaultDescription
container
HTMLElement | ShadowRoot | RefObject<HTMLElement | ShadowRoot | null> | null
–

A parent element to render the portal element into.

keepMounted
boolean
false

Whether to keep the portal mounted in the DOM while the popup is hidden.

MenuRadioGroup

Accepts className, style and render, plus every native attribute of the element it renders.

PropTypeDefaultDescription
children
ReactNode
–

The content of the component.

defaultValue
any
–

The uncontrolled value of the radio item that should be initially selected.

To render a controlled radio group, use the value prop instead.

disabled
boolean
false

Whether the component should ignore user interaction.

onValueChange
((value: any, eventDetails: MenuRootChangeEventDetails) => void)
–

Function called when the selected value changes.

value
any
–

The controlled value of the radio item that should be currently selected.

To render an uncontrolled radio group, use the defaultValue prop instead.

MenuRadioItem

Accepts className, style and render, plus every native attribute of the element it renders.

PropTypeDefaultDescription
valueReq
any
–

Value of the radio item. This is the value that will be set in the MenuRadioGroup when the item is selected.

closeOnClick
boolean
false

Whether to close the menu when the item is clicked.

disabled
boolean
false

Whether the component should ignore user interaction.

label
string
–

Overrides the text used for keyboard text navigation and filtering. Falls back to the rendered text when not provided.

nativeButton
boolean
false

Whether the component renders a native <button> element when replacing it via the render prop. Set to true if the rendered element is a native button.

onClick
((event: BaseUIEvent<MouseEvent<HTMLDivElement, MouseEvent>>) => void)
–

The click handler for the menu item.

MenuSeparator

Accepts className, style and render, plus every native attribute of the element it renders.

PropTypeDefaultDescription
orientation
"horizontal"|"vertical"
'horizontal'

The orientation of the separator.

MenuShortcut

Accepts render, plus every native <kbd> attribute.

MenuSub

PropTypeDefaultDescription
actionsRef
RefObject<MenuRootActions | null>
–

A ref to imperative actions.

  • unmount: Ends the closing phase of the menu after an externally controlled closing animation finishes. Call preventUnmountOnClose() in onOpenChange first, otherwise the menu completes closing on its own. Whether it leaves the DOM is decided by keepMounted on the portal.
  • close: Closes the menu imperatively when called.
children
ReactNode
–

The content of the submenu.

closeParentOnEsc
boolean
false

When in a submenu, determines whether pressing the Escape key closes the entire menu, or only the current child menu.

defaultOpen
boolean
false

Whether the menu is initially open.

To render a controlled menu, use the open prop instead.

disabled
boolean
false

Whether the component should ignore user interaction.

highlightItemOnHover
boolean
true

Whether moving the pointer over items should highlight them. Disabling this prop allows CSS :hover to be differentiated from the :focus (data-highlighted) state.

loopFocus
boolean
true

Whether to loop keyboard focus back to the first item when the end of the list is reached while using the arrow keys.

onItemHighlighted
((highlightedItem: HTMLElement, eventDetails: MenuRootHighlightEventDetails) => void)
–

Callback fired when an item is highlighted or unhighlighted. Receives the highlighted item element (or undefined if no item is highlighted) and details containing the reason for the change, the event, and the item's text label. The reason can be:

  • 'keyboard': the highlight changed due to keyboard navigation.
  • 'pointer': the highlight changed due to pointer hovering. The event may be a MouseEvent rather than a PointerEvent.
  • 'none': the highlight changed for another reason, such as automatic highlighting while filtering, the item list changing, or the popup opening or closing.
onOpenChange
((open: boolean, eventDetails: MenuRootChangeEventDetails) => void)
–

Event handler called when the menu is opened or closed.

onOpenChangeComplete
((open: boolean) => void)
–

Event handler called after any animations complete when the menu is opened or closed.

open
boolean
–

Whether the menu is currently open.

orientation
"horizontal"|"vertical"
'vertical'

The visual orientation of the menu. Controls whether roving focus uses up/down or left/right arrow keys.

MenuSubPopup

Accepts className, style and render, plus every native attribute of the element it renders.

PropTypeDefaultDescription
align
"center"|"start"|"end"
start

How the calendar lines up with the trigger along that side.

alignOffset
number|OffsetFunction
–

Additional offset along the alignment axis, in pixels.

children
ReactNode
–

The content of the component.

finalFocus
boolean | RefObject<HTMLElement | null> | ((closeType: InteractionType) => boolean | void | HTMLElement | null)
–

Determines the element to focus when the menu is closed.

  • false: Do not move focus.
  • true: Move focus based on the default behavior (trigger or previously focused element).
  • RefObject: Move focus to the ref element.
  • function: Called with the interaction type (mouse, touch, pen, or keyboard). Return an element to focus, true to use the default behavior, or false/undefined to do nothing.
sideOffset
number|OffsetFunction
0

The gap between the trigger and the calendar, in pixels.

MenuSubTrigger

Accepts className, style and render, plus every native attribute of the element it renders.

PropTypeDefaultDescription
closeDelay
number
0

How long to wait before closing the menu that was opened on hover. Specified in milliseconds.

Requires the openOnHover prop.

delay
number
100

How long to wait before the menu may be opened on hover. Specified in milliseconds.

Requires the openOnHover prop.

disabled
boolean
false

Whether the component should ignore user interaction.

icon
ReactNode
–

Replaces this icon. Accepts any node; null renders no icon. Takes precedence over IconProvider.

inset
boolean
–

Whether to indent the item so its text lines up with items that have an icon.

label
string
–

Overrides the text used for keyboard text navigation and filtering. Falls back to the rendered text when not provided.

nativeButton
boolean
false

Whether the component renders a native <button> element when replacing it via the render prop. Set to true if the rendered element is a native button.

onClick
((event: BaseUIEvent<MouseEvent<HTMLDivElement, MouseEvent>>) => void)
–

The click handler for the menu item.

openOnHover
boolean
true

Whether the menu should also open when the trigger is hovered.

MenuTrigger

Accepts className, style and render, plus every native attribute of the element it renders.

PropTypeDefaultDescription
children
ReactNode
–

The content of the component.

closeDelay
number
0

How long to wait before closing the menu that was opened on hover. Specified in milliseconds.

Requires the openOnHover prop.

delay
number
100

How long to wait before the menu may be opened on hover. Specified in milliseconds.

Requires the openOnHover prop.

disabled
boolean
false

Whether the component should ignore user interaction.

handle
MenuHandle<unknown>
–

A handle to associate the trigger with a menu.

nativeButton
boolean
true

Whether the component renders a native <button> element when replacing it via the render prop. Set to false if the rendered element is not a button (for example, <div>).

openOnHover
boolean
–

Whether the menu should also open when the trigger is hovered.

payload
unknown
–

A payload to pass to the menu when it is opened.

Helpers

MenuCreateHandle is called, not rendered. It creates a handle: pass it as handle to a trigger and to the root, and the trigger can sit anywhere in the tree, outside the root.