ContextMenu
context-menuOpens contextual action items at the pointer with a danger treatment.
Usage
Basic usage
Right-click (or long-press) on the Trigger area to pop up a menu, and the menu is anchored to the cursor. Item supports disabled and variant="danger".
<ContextMenu>
<ContextMenuTrigger className="...right-click this area">
Right click on this area
</ContextMenuTrigger>
<ContextMenuContent>
<ContextMenuItem>Edit</ContextMenuItem>
<ContextMenuItem>Copy</ContextMenuItem>
<ContextMenuItem disabled>Archive (Disabled)</ContextMenuItem>
<ContextMenuSeparator />
<ContextMenuItem variant="danger">Delete</ContextMenuItem>
</ContextMenuContent>
</ContextMenu>Group with title
Use ContextMenuGroup + ContextMenuGroupLabel to add a group title to a group of commands.
<ContextMenuContent>
<ContextMenuGroup>
<ContextMenuGroupLabel>Operation</ContextMenuGroupLabel>
<ContextMenuItem>Edit</ContextMenuItem>
<ContextMenuItem>Copy</ContextMenuItem>
</ContextMenuGroup>
<ContextMenuSeparator />
<ContextMenuItem variant="danger">Delete</ContextMenuItem>
</ContextMenuContent>Checkbox and radio items
ContextMenuCheckboxItem is a setting that toggles on and off (role=menuitemcheckbox); ContextMenuRadioGroup plus ContextMenuRadioItem forms a set of mutually exclusive options (role=menuitemradio). aria-checked lets a screen reader announce the current selection; a tick drawn by hand on a plain Item is indistinguishable on screen but loses that semantic.
<ContextMenuContent>
<ContextMenuCheckboxItem defaultChecked>Pin this task</ContextMenuCheckboxItem>
<ContextMenuSeparator />
<ContextMenuGroup>
<ContextMenuGroupLabel>Priority</ContextMenuGroupLabel>
<ContextMenuRadioGroup defaultValue="medium">
<ContextMenuRadioItem value="low">Low</ContextMenuRadioItem>
<ContextMenuRadioItem value="medium">Medium</ContextMenuRadioItem>
<ContextMenuRadioItem value="high">High</ContextMenuRadioItem>
</ContextMenuRadioGroup>
</ContextMenuGroup>
</ContextMenuContent>Cascading submenu
ContextMenuSub nests SubTrigger + SubContent, expanded from the right side of the parent item, supporting multi-level nesting.
<ContextMenuSub>
<ContextMenuSubTrigger>Move to</ContextMenuSubTrigger>
<ContextMenuSubContent>
<ContextMenuItem>Inbox</ContextMenuItem>
<ContextMenuItem>Project A</ContextMenuItem>
<ContextMenuSeparator />
<ContextMenuSub>
<ContextMenuSubTrigger>More groups</ContextMenuSubTrigger>
<ContextMenuSubContent>
<ContextMenuItem>Archive</ContextMenuItem>
<ContextMenuItem>Star</ContextMenuItem>
</ContextMenuSubContent>
</ContextMenuSub>
</ContextMenuSubContent>
</ContextMenuSub>When to use
Use ContextMenu to open pointer-anchored actions from a right click or long press within a target region, including Edit, Copy, Delete, nested submenus, and groups. Use Command for a global searchable command entry or Toolbar for persistent controls. ContextMenu reuses Menu styling and supports variant="danger" for destructive items.
Import
import { ContextMenu, ContextMenuTrigger, ContextMenuContent, ContextMenuItem, ContextMenuCheckboxItem, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuGroup, ContextMenuGroupLabel, ContextMenuSub, ContextMenuSubTrigger, ContextMenuSubContent } from "@hulianui/ui"Props
ContextMenuItem
| Name | Type | Default | Description |
|---|---|---|---|
| disabled | boolean | - | Whether the item is unavailable. |
| closeOnClick | boolean | true | Whether selecting the item closes the menu. |
| label | string | - | Text override for keyboard type-ahead, needed when children are not plain text. |
| variant | "default" | "danger" | "default" | Visual treatment; use danger for destructive actions. |
| className | string | - | Additional class name. |
ContextMenuCheckboxItem: a setting that can be toggled on or off. Renders role="menuitemcheckbox" plus aria-checked.
| Name | Type | Default | Description |
|---|---|---|---|
| checked | boolean | - | Whether the item is ticked (controlled). For an uncontrolled item use defaultChecked instead. |
| defaultChecked | boolean | false | Whether the item is initially ticked (uncontrolled). |
| disabled | boolean | false | Whether the item is unavailable. |
| closeOnClick | boolean | false | Whether selecting the item closes the menu. Checkbox items keep the menu open by default so several can be toggled in a row. |
| label | string | - | Text override for keyboard type-ahead. |
| variant | "default" | "danger" | "default" | Visual treatment; use danger for destructive actions. |
| className | string | - | Additional class name. |
ContextMenuRadioGroup: container for a set of mutually exclusive options. Every ContextMenuRadioItem must be nested inside one.
| Name | Type | Default | Description |
|---|---|---|---|
| value | string | - | Value of the currently selected item (controlled). For an uncontrolled group use defaultValue instead. |
| defaultValue | string | - | Value of the initially selected item (uncontrolled). |
| disabled | boolean | false | Whether the whole group is unavailable. |
| className | string | - | Additional class name. |
ContextMenuRadioItem: one option in a mutually exclusive set. Renders role="menuitemradio" plus aria-checked.
| Name | Type | Default | Description |
|---|---|---|---|
| value* | string | - | Value of this item; it is selected when it equals the value of its ContextMenuRadioGroup. |
| disabled | boolean | false | Whether the item is unavailable. |
| closeOnClick | boolean | false | Whether selecting the item closes the menu. Radio items keep the menu open by default, so pass true if picking a value should dismiss it. |
| label | string | - | Text override for keyboard type-ahead. |
| variant | "default" | "danger" | "default" | Visual treatment; use danger for destructive actions. |
| className | string | - | Additional class name. |
ContextMenuSubTrigger: props disabled / label / variant?: "default" \| "danger" / className; slot children.
ContextMenuContent / ContextMenuSubContent: prop className; slot children.
ContextMenuTrigger / Group / GroupLabel / Separator / Sub: structural wrappers around the corresponding Base UI primitives, forwarding children and className.
Events
| Event | Type | Description |
|---|---|---|
| onClick | MouseEventHandler<HTMLElement> | Click handler for ContextMenuItem, ContextMenuCheckboxItem, and ContextMenuRadioItem. |
| onCheckedChange | (checked: boolean) => void | Called when a ContextMenuCheckboxItem is ticked or unticked. |
| onValueChange | (value: string) => void | Called when the value of a ContextMenuRadioGroup changes. |
Slots
| Slot | Type | Description |
|---|---|---|
| children | ReactNode | Content of a ContextMenuItem; for ContextMenuCheckboxItem and ContextMenuRadioItem it renders in the second column, to the right of the selection marker; a ContextMenuRadioGroup holds a set of ContextMenuRadioItem elements. |
Example
<ContextMenu>
<ContextMenuTrigger className="flex h-28 items-center justify-center border border-dashed">
Right-click this area
</ContextMenuTrigger>
<ContextMenuContent>
<ContextMenuItem>Edit</ContextMenuItem>
<ContextMenuItem disabled>Archive (unavailable)</ContextMenuItem>
<ContextMenuSub>
<ContextMenuSubTrigger>Move to</ContextMenuSubTrigger>
<ContextMenuSubContent>
<ContextMenuItem>Project A</ContextMenuItem>
<ContextMenuItem>Project B</ContextMenuItem>
</ContextMenuSubContent>
</ContextMenuSub>
<ContextMenuSeparator />
<ContextMenuItem variant="danger">Delete</ContextMenuItem>
</ContextMenuContent>
</ContextMenu>Checkbox and radio items, the usual shape of a task-card context menu:
<ContextMenuContent>
<ContextMenuCheckboxItem defaultChecked>Pin this task</ContextMenuCheckboxItem>
<ContextMenuSeparator />
<ContextMenuGroup>
<ContextMenuGroupLabel>Priority</ContextMenuGroupLabel>
<ContextMenuRadioGroup value={priority} onValueChange={setPriority}>
<ContextMenuRadioItem value="low" closeOnClick>Low</ContextMenuRadioItem>
<ContextMenuRadioItem value="medium" closeOnClick>Medium</ContextMenuRadioItem>
<ContextMenuRadioItem value="high" closeOnClick>High</ContextMenuRadioItem>
</ContextMenuRadioGroup>
</ContextMenuGroup>
</ContextMenuContent>(closeOnClick dismisses the menu once a value is picked; it defaults to false, which keeps the menu open for further edits.)
Usage guidelines
- Do not build a set of options out of `ContextMenuItem` plus a hand-drawn tick. It looks exactly like
ContextMenuCheckboxItem/ContextMenuRadioItem, which is why the mistake is invisible: the element falls back torole="menuitem"with noaria-checked, so screen reader users hear a few peer actions instead of one group of mutually exclusive options, and cannot tell which one is selected. UseContextMenuCheckboxItemfor toggleable settings andContextMenuRadioGroupplusContextMenuRadioItemfor exclusive choices. ContextMenuRadioItemmust be nested in aContextMenuRadioGroup, otherwise it never renders a selected state.- The selection marker occupies a first column as wide as the
size-4icon of a plainContextMenuItem, so text left edges line up in a mixed menu. Keep icons on plain items atsize-4. - Wrap grouped entries in
ContextMenuGroupand label them withContextMenuGroupLabelfor correct group semantics. Bare items form one unlabelled list. - When
ContextMenuItemchildren contain rich content such as an icon, addlabelfor keyboard type-ahead.
Related
Command · Toolbar · Accordion · Collapsible · Link · AnimatedThemeToggler
Playground
<ContextMenu>
<ContextMenuTrigger>Right-click this area</ContextMenuTrigger>
<ContextMenuContent>
<ContextMenuItem>Edit</ContextMenuItem>
<ContextMenuSub>
<ContextMenuSubTrigger>Move to</ContextMenuSubTrigger>
<ContextMenuSubContent>
<ContextMenuItem>Project A</ContextMenuItem>
</ContextMenuSubContent>
</ContextMenuSub>
<ContextMenuSeparator />
<ContextMenuItem variant="danger">Delete</ContextMenuItem>
</ContextMenuContent>
</ContextMenu>