Menu
Dropdown menu for structured actions with grouped items, submenus, checkbox and radio items, and horizontal layouts.
import { Menu } from "@plexui/ui/components/Menu";Examples
Overview
Natural sizing
Horizontal (icons only)
Horizontal (icons with labels)
Grouped items
Submenus
Checkbox items
Radio items
Item actions
Destructive items
API
Note: Menu prevents Tab from advancing focus. For generic popover content use Popover instead.
Menu (root)
| Prop | Type | Default | Description |
|---|---|---|---|
forceOpen | boolean | — | Keep menu open (controlled) |
onOpen | () => void | — | Called when menu opens |
onClose | () => void | — | Called when menu closes |
modal | boolean | false | Whether menu is modal (focus trap) |
Menu.Trigger: Renders its child (e.g. a Button) as the element that toggles the menu. Other props (aria-*, handlers, ref) reach the child.
| Prop | Type | Default | Description |
|---|---|---|---|
disabled | boolean | false | Prevent the menu from opening |
Menu.Content
| Prop | Type | Default | Description |
|---|---|---|---|
width | number | "auto" | "auto" | Panel width in px |
minWidth | number | "auto" | 300 | Minimum panel width in px (vertical layout) |
maxHeight | number | — | Maximum panel height in px |
side | "top" | "right" | "bottom" | "left" | "bottom" | Preferred placement |
sideOffset | number | 5 | Distance from the trigger in px |
align | "start" | "center" | "end" | "center" | Alignment relative to trigger |
alignOffset | number | -5 | Offset from the start or end alignment in px |
layout | "vertical" | "horizontal" | "vertical" | Layout direction. Use horizontal for icon toolbars |
size | "sm" | "md" | "lg" | "md" | Size of horizontal menu items (icon size + padding) |
onCloseAutoFocus | (event: Event) => void | — | Called before focus returns to the trigger; call event.preventDefault() to keep it from moving there |
Menu.Item: List item. Use onSelect or onClick for actions; without either the item is non-interactive content.
| Prop | Type | Default | Description |
|---|---|---|---|
description | ReactNode | — | Second line under the label. The label turns semibold on its own |
onSelect | (event: Event) => void | — | Called when item is selected; call event.preventDefault() to keep the menu open |
onClick | (event: MouseEvent) => void | — | Called when the item is clicked; also makes the item interactive |
disabled | boolean | false | Disable the item |
danger | boolean | false | Destructive action: the item is drawn in the danger color |
className | string | — | Applied to the item |
Menu.Link: Item that navigates. Internal paths render the link component from PlexUIProvider; absolute http(s) URLs open in a new tab. Pass href or to, disabled (a disabled link does not navigate), as and link props; danger marks a destructive destination.
Menu.Separator: Divider between items. No props.
Menu.Group: Groups related items. Wraps Menu.Item, Menu.Link, or Menu.Label. No specific props.
Menu.Label: Non-interactive label for a group. Accepts className.
Menu.Sub / Menu.SubTrigger / Menu.SubContent: Submenu wrapper (with forceOpen, onOpen and onClose), trigger (with disabled), and content panel (with width, minWidth, maxHeight, sideOffset and alignOffset).
Menu.CheckboxItem
| Prop | Type | Default | Description |
|---|---|---|---|
checked | boolean | "indeterminate" | — | Checked state |
onCheckedChange | (checked: boolean) => void | — | When checkbox toggles |
onSelect | (event: Event) => void | — | Use with preventDefault() to keep menu open |
indicatorPosition | "start" | "end" | "end" | Checkbox position |
indicatorVariant | "solid" | "ghost" | "solid" | Checkbox indicator style |
disabled | boolean | — | Disable the item |
Menu.RadioGroup / Menu.RadioItem: Radio group: value, onChange and indicatorPosition (default "end"); RadioItem: value, disabled and onSelect.
Menu.ItemActions / Menu.ItemAction: ItemActions wraps hover actions; ItemAction accepts onClick and closes the menu.
Styling
Menu reads these component tokens. Override them at any scope to restyle it:
--menu-checkbox-indicator-size: checkbox indicator size (defaultvar(--font-text-lg-size))--menu-font-size: font size (defaultvar(--font-text-sm-size))--menu-gutter: gutter (defaultspacing(1.5))--menu-item-background-color: item background color (defaultlight-dark(var(--alpha-08), var(--alpha-10)))--menu-item-gap: item gap (defaultspacing(1.5))--menu-item-padding: item padding (defaultspacing(1.5) spacing(2))--menu-line-height: line height (defaultvar(--font-text-sm-line-height))--menu-radio-indicator-hole-size: radio indicator hole size (defaultvar(--font-text-3xs-size))--menu-radio-indicator-size: radio indicator size (defaultvar(--font-text-lg-size))--menu-radius: radius (defaultvar(--radius-xl))--menu-separator-background-color: separator background color (defaultvar(--color-border))--menu-separator-gutter: separator gutter (defaultvar(--menu-gutter) calc(-1 * var(--menu-gutter)))--radio-group-indicator-background-color: indicator background color (defaultvar(--color-background-primary-solid))--radio-group-indicator-border-color: indicator border color (defaultvar(--color-border-primary-outline))--radio-group-indicator-border-color-hover: indicator border color hover (defaultvar(--alpha-25))--radio-group-indicator-hole-background-color: indicator hole background color (defaultvar(--color-text-primary-solid))