Context Menu
Right-click menu that opens at the cursor over a region, for row actions, canvas commands, and editor shortcuts.
Description
ContextMenu is a right-click menu built on the same surface as Dropdown. It wraps a region in a ContextMenu.Trigger, and on contextmenu (right-click, long-press, or the keyboard menu key) it opens a ContextMenu.Popover at the pointer. Every part mirrors its Dropdown.* counterpart, so ContextMenu.Menu, ContextMenu.Section, ContextMenu.Header, ContextMenu.Item, and ContextMenu.Separator behave exactly as they do in a dropdown. size is set on the root and cascades to every item, label, and icon.
Reach for it when the actions belong to a thing on screen rather than to a button: file and list rows, canvas objects, table cells, an editable text field. Because the menu opens at the cursor, it keeps the pointer close to the target and does not need a visible trigger control.
Unlike a dropdown, there is no button to click: the affordance is the region itself, so give the trigger a hover state and make sure a keyboard path exists. Don't use a context menu as the primary way to reach an action (some users never right-click) and don't use it for form values (use Select) or for a labeled button menu (use Dropdown).
Because the parts alias Dropdown.*, they carry the same tiers: ContextMenu.Item (with a leading icon and size) and ContextMenu.Separator are free. Grouped sections and headers, a pinned search bar, smart items (secondary text, trailing shortcuts or controls), selection modes, and the footer slot are Pro (add it with a Pro seat via add context-menu).
Installation
Anatomy
Usage
Examples
The free tier covers ContextMenu.Item (with a leading icon and size) and ContextMenu.Separator, as in the demo above. Everything richer is a Pro preview, marked with a Pro badge; the live demo still runs, but the source needs a Pro seat.
Grouping
The free tier separates runs of items with ContextMenu.Separator. Pro adds ContextMenu.Section + ContextMenu.Header for labeled groups. A destructive command takes variant="danger".
Sizes
Three sizes (xs, sm, md) set on the root cascade to radius, item height, label, and icon size. sm is the default.
On a text field
Wrap a focusable control and pass tabIndex={-1} to the trigger so it does not add a second tab stop. Capture the selection in onContextMenu before opening, because focus leaves the field once the menu is shown. Trailing keyboard-shortcut hints go in the item's trailing slot.
File list
Each row owns its own ContextMenu, so the actions operate on that row. A leading icon marks each command and a danger item removes the row, all with free-tier parts.
Accessibility
ContextMenu inherits React Aria's menu keyboard model once open. The native contextmenu event is dispatched by right-click, long-press, and the keyboard menu key (or Shift+F10), so make the trigger focusable and it works for keyboard users too. When the trigger already wraps a focusable control, pass tabIndex={-1} to avoid a duplicate tab stop.
ARIA notes:
- The trigger renders with
aria-haspopup="menu"andaria-expanded; React Aria wiresrole="menu"on the list androle="menuitem"(ormenuitemcheckbox/menuitemradiounder aselectionMode) on each row. The popover manages focus while the menu is open. - Keyboard-invoked events can report
(0,0)coordinates; the trigger falls back to anchoring the menu to its own box in that case so it still opens sensibly. - Activating a row closes the menu by default. For a row that holds an interactive control, pass
shouldCloseOnSelect={false}. Give aContextMenu.Menuanaria-labelwhen it has no visible label. - For the full focus, collection, and typeahead behavior, see the React Aria Menu docs.
Styling
Tailwind override: pass className to merge Tailwind classes on ContextMenu.Popover or any sub-part (merged via cn()):
Data slots and attributes: the component sets these for CSS targeting:
data-slot="context-menu-trigger"on the trigger region,context-menu-anchoron the invisible cursor anchor,context-menu-popoveron the surface, andcontext-menu-menuon the list. The remaining parts reuse the dropdown slots:dropdown-section,dropdown-header,dropdown-separator,dropdown-item,dropdown-item-label/dropdown-item-description/dropdown-item-container/dropdown-item-content/dropdown-item-indicator, anddropdown-footer.data-size="xs" | "sm" | "md"mirrors the root size;data-variant="default" | "danger"on the item.- React Aria manages
data-focused,data-selected, anddata-disabledon each item; wrappers style throughgroup-data-[focused]/itemandgroup-data-[selected]/item. - The trigger carries
cursor-context-menu; passclassName(last-wins) to override it per instance, for examplecursor-textover an editable field.
Target a state in CSS:
Related Components
- Dropdown Menu: the same menu surface opened from a labeled button instead of a right-click.
- Select: form-value picker bound to a
Field. Use it when the chosen value is what the form submits. - Popover (Pro): arbitrary content with no menu semantics or roving focus.
- Command (Pro): a searchable command palette in a modal shell.
API Reference
ContextMenu.* parts are aliases of the Dropdown.* parts, so their props match. The context-specific parts are the root, ContextMenu.Trigger, and ContextMenu.Popover.
ContextMenu
The root. Provides the size context, tracks the open state, and moves the cursor anchor. Its children are a ContextMenu.Trigger and a ContextMenu.Popover.
Props
Variants
ContextMenu.Trigger
The right-click region. A focusable <div> (extends React.ComponentProps<"div">) that opens the menu on contextmenu and positions it at the pointer.
Props
ContextMenu.Popover
The floating surface. Opens at the cursor via a virtual anchor. Extends React Aria's PopoverProps; defaults to placement="bottom start" and offset={0}.
Props
ContextMenu.Menu
The list. Extends React Aria's MenuProps, so all collection and selection props (selectionMode, selectedKeys, onSelectionChange, disabledKeys, items, renderEmptyState, aria-label, …) pass through, identical to Dropdown.Menu.
ContextMenu.Item
A menu row. Aliases Dropdown.Item. A plain label with an optional leading icon, variant="danger" for a destructive row, and size are free; description, trailing, and indicator opt into the smart layout (Pro). id, textValue, onAction, isDisabled, and shouldCloseOnSelect pass through from React Aria's MenuItemProps.
Variants
ContextMenu.Separator
A thin divider between runs of items. Aliases Dropdown.Separator and, like ContextMenu.Item, is free. Extends React Aria's SeparatorProps; accepts className.
Other parts (Pro)
Aliases of the matching Dropdown parts; see the Dropdown Menu API for their props. Every part below is Pro, matching the Dropdown tiers.