Capítulo 15 de 43

Chapter 15: Context Menu

Core Idea

A menu that appears at the pointer position on right-click (or long-press on touch), supporting submenus, checkable items, radio groups, and full collision-aware positioning — the desktop-context-menu counterpart to DropdownMenu.

Key Concepts

  • Anatomy: RootTrigger (wraps the right-clickable target) → PortalContentItem / Group (+ Label) / CheckboxItem (+ ItemIndicator) / RadioGroupRadioItem (+ ItemIndicator) / SubSubTrigger + PortalSubContent / Separator.
  • Roving tabindex: focus moves between items via a single tab stop that shifts internally, per the Menu WAI-ARIA pattern — not individual per-item tab stops.
  • modal (default true): controls whether outside pointer/focus interactions are blocked while open.
  • Collision handling: avoidCollisions, collisionBoundary, collisionPadding, sticky on Content — same positioning engine shared by Popover/DropdownMenu/Select/HoverCard.
  • --radix-context-menu-content-transform-origin: exposes the computed transform origin so open/close animations can scale from the correct corner.

Code Examples

<ContextMenu.Root>
  <ContextMenu.Trigger>Right-click here</ContextMenu.Trigger>
  <ContextMenu.Portal>
    <ContextMenu.Content>
      <ContextMenu.Item>Item 1</ContextMenu.Item>
      <ContextMenu.Sub>
        <ContextMenu.SubTrigger>More…</ContextMenu.SubTrigger>
        <ContextMenu.Portal>
          <ContextMenu.SubContent>
            <ContextMenu.Item>Sub item</ContextMenu.Item>
          </ContextMenu.SubContent>
        </ContextMenu.Portal>
      </ContextMenu.Sub>
    </ContextMenu.Content>
  </ContextMenu.Portal>
</ContextMenu.Root>
  • What it demonstrates: nesting a submenu (Sub/SubTrigger/SubContent) inside the top-level menu content.

Reference Tables

PartNotable props
Contentloop, alignOffset, avoidCollisions, collisionBoundary, collisionPadding, sticky, hideWhenDetached
Itemdisabled, onSelect, textValue (for typeahead when content isn't plain text)
CheckboxItemchecked/onCheckedChange (supports "indeterminate")
RadioItemvalue
SubTriggerdisabled, textValue

Key Takeaways

  1. Every menu-item variant supports keyboard typeahead by default — type a letter to jump to the matching item; use textValue when the item's visible content isn't a plain string.
  2. Submenus (Sub) open/close with ArrowRight/ArrowLeft depending on reading direction (dir on Root), not just click/hover.
  3. modal={true} (the default) blocks outside interaction while open — set modal={false} if the menu should coexist with interaction elsewhere on the page.

Connects To

  • Dropdown Menu: near-identical API, triggered by click instead of right-click/long-press.
  • Menubar: composes several menus like this one into a persistent horizontal bar.
  • Popover / Select / HoverCard: share the same collision-aware positioning props on Content.