Context menu
The right-click menu for an area or an object, opened at the pointer. Same skin and keyboard model as Dropdown menu. Source: src/components/ui/context-menu.tsx.
Default
Right-click the area, long-press it on touch, or focus it and press Shift+F10. Inside, arrows move, → opens the submenu, Esc closes and focus goes back to the area.
Right-click hereLong-press on touch · Shift+F10 or the Menu key when focused
last: nothing yet · grid on · rulers off · zoom fitPer row
One menu per object. The open row keeps a tint fill (data-state=open on the trigger) so it is clear what the menu acts on, and the label repeats its name.
- Launch brief.md
- Pricing research.pdf
- Interview notes.md
Motion and layering
Shares DropdownMenu's surface and motion strings; keyframes, so not interruptible.
| Value | Token | Usage |
|---|---|---|
| pointer | Opens at the cursor (or the long-press point), not against an edge of the trigger. | |
| 140ms | Fade and scale from 95%, as on DropdownMenu. | |
| 90ms | Fade and scale out. | |
| 50 | The brand ladder (--z-dropdown 100) is defined but not wired in yet. | |
| max-h | Long menus scroll inside the viewport. |
Props
| Part / prop | Type | Default | Description |
|---|---|---|---|
| ContextMenu | Radix ContextMenu.Root | — | onOpenChange, modal. There is no open prop: the pointer opens it. |
| ContextMenuTrigger | Radix ContextMenu.Trigger | — | The area that listens for contextmenu and long-press. disabled. Gets data-state=open. |
| ContextMenuContent | Radix ContextMenu.Content | — | Portals itself. loop, alignOffset, collisionPadding. |
| ContextMenuItem | Radix ContextMenu.Item | — | onSelect, disabled, textValue. |
| variant | "default" | "destructive" | "default" | Destructive turns text, icon and focus fill red. |
| inset | boolean | false | 32px left padding. Also on Label and SubTrigger. |
| ContextMenuCheckboxItem | Radix CheckboxItem | — | checked, onCheckedChange. Always has the check gutter (no indicator prop, unlike the dropdown). |
| ContextMenuRadioGroup, RadioItem | Radix | — | value, onValueChange / value. Always has the dot gutter. |
| ContextMenuLabel | Radix Label | — | Heading row; inset available. |
| ContextMenuGroup, Separator | Radix | — | Grouping and a hairline that bleeds to the edges. |
| ContextMenuShortcut | ComponentProps<"span"> | — | Right-aligned slot for text or Kbd. Display only. |
| ContextMenuSub, SubTrigger, SubContent | Radix | — | Nested menu. SubContent is not portalled. |
| ContextMenuPortal | Radix Portal | — | Exported; Content already portals. |
Best practices
When to use
- A shortcut for power users, on canvases, files and list rows.
- Never the only way to an action: put the same items behind a visible ⋯ DropdownMenu.
Behavior
- Order items as the dropdown does, so muscle memory carries across both.
- Mark the target while open with data-[state=open] styles on the trigger.
- Shortcuts are display only; bind them elsewhere.
Accessibility
- Make the trigger focusable (tabIndex={0}) so Shift+F10 and the Menu key reach it.
- Give an unlabelled area an aria-label that mentions the menu.
- Focus returns to the trigger on Esc.
Content
- Short verbs. Destructive last, behind a separator.
- A label row naming the object helps when the target is small.