Menu
A list of actions behind a button.
import { Button, Menu } from "@openperf/deft";
import { Preview } from "../../src/Preview";
export default function MenuBasic() {
return (
<Preview overlay={true}>
<Menu.Root>
<Menu.Trigger render={<Button.Root />}>Open menu</Menu.Trigger>
<Menu.Content>
{Array.from({ length: 3 }, (_, index) => (
<Menu.Item key={index}>Item {index + 1}</Menu.Item>
))}
</Menu.Content>
</Menu.Root>
</Preview>
);
}
- Use a menu for secondary actions that don’t fit in a toolbar. To pick a value for a form, use a Select.
- Separate groups of ordinary actions with
Menu.Separator. - Put the destructive action last and set
tone="danger"on it. - In menus opened from the action bar, set
size="sm"on every item to match its smaller buttons. Menu.CheckboxItemkeeps the menu open on click, so several options can be toggled in a row.
Item content
import { Button, Menu } from "@openperf/deft";
import { IconPlus } from "@tabler/icons-react";
import { Preview } from "../../src/Preview";
export default function MenuItemContent() {
return (
<Preview overlay={true}>
<Menu.Root>
<Menu.Trigger render={<Button.Root />}>Open menu</Menu.Trigger>
<Menu.Content>
<Menu.Item>
<IconPlus />
Item 1
</Menu.Item>
<Menu.Item description="Description">Item 2</Menu.Item>
<Menu.Item trailing="12">Item 3</Menu.Item>
</Menu.Content>
</Menu.Root>
</Preview>
);
}
Render an icon as the first child to make a familiar action easier to scan, and add a description only when the action needs more context. Put a keyboard shortcut or a count in trailing, kept secondary to the label. Icons take the item tone, including danger.
Radio groups
import { Button, Menu } from "@openperf/deft";
import { Preview } from "../../src/Preview";
export default function MenuRadioGroups() {
return (
<Preview overlay={true}>
<Menu.Root>
<Menu.Trigger render={<Button.Root />}>Open menu</Menu.Trigger>
<Menu.Content>
<Menu.RadioGroup defaultValue="option-1">
<Menu.GroupLabel>Label</Menu.GroupLabel>
{Array.from({ length: 3 }, (_, index) => (
<Menu.RadioItem key={index} value={`option-${index + 1}`}>
Option {index + 1}
</Menu.RadioItem>
))}
</Menu.RadioGroup>
</Menu.Content>
</Menu.Root>
</Preview>
);
}
Use Menu.RadioGroup for mutually exclusive choices; the selected item shows a check on the right. Menu.GroupLabel names the choice set, such as Sort by. Use separators rather than labels for groups of ordinary actions.
API
align?"start" | "center" | "end"
On Content.
"start" | "center" | "end""start"side?"top" | "bottom" | "left" | "right" | "inline-start" | "inline-end"
On Content.
"top" | "bottom" | "left" | "right" | "inline-start" | "inline-end""bottom"sideOffset?number
On Content.
number4tone?"default" | "danger"
On Item.
"default" | "danger""default"size?"sm" | "md"
On Item, CheckboxItem and RadioItem.
"sm" | "md""md"description?ReactNode
On Item, CheckboxItem, RadioItem and SubmenuTrigger. A second line in muted text.
ReactNodetrailing?ReactNode
On Item and CheckboxItem. A shortcut or count on the right.
ReactNodecloseOnClick?boolean
On CheckboxItem.
booleanfalseParts: Root, CheckboxItem, Content, Footer, GroupLabel, Item, RadioItem, Separator, SubmenuTrigger, plus the other Base UI Menu parts, such as Trigger, RadioGroup, Group and SubmenuRoot. Content wraps Portal, Positioner and Popup; Footer passes its props to the native div. Built on Base UI Menu.