Capítulo 20 de 51

Chapter 20: Context Menu

Core Idea

A right-click (long-press on touch) triggered menu sharing the full Menu part vocabulary (items, submenus, radio/checkbox items) — must always be an enhancement, never the only way to reach an action, since context menus are hard to discover on touch devices and with assistive technology.

Key Concepts

  • Usage guideline (critical): always provide a visible control for every action also reachable via the context menu — context menus are a discoverability dead-end for touch/AT users.
  • Anatomy: RootTrigger, PortalBackdrop, PositionerPopup (Arrow, Item, LinkItem, Separator, SubmenuRootSubmenuTrigger, GroupGroupLabel, RadioGroupRadioItemRadioItemIndicator, CheckboxItemCheckboxItemIndicator) — identical item vocabulary to Menu (ch027), positioned at the pointer instead of anchored to a trigger element.
  • Positioning: Positioner still exposes the standard side/align/collisionBoundary/sticky family, but positions relative to the pointer/long-press location rather than the Trigger element.
  • Nesting: SubmenuRoot/SubmenuTrigger for nested submenus, openOnHover/delay/closeDelay on SubmenuTrigger control hover-opening behavior — same pattern as Menu.
  • closeParentOnEsc: on Root/SubmenuRoot, controls whether Esc in a submenu also closes the parent context menu.

Reference Tables

PartNotable propsNotable data attributes
Rootopen/onOpenChange, closeParentOnEsc, loopFocus, highlightItemOnHover
Itemlabel, onClick, closeOnClick, disableddata-highlighted, data-disabled
CheckboxItemchecked/onCheckedChange, closeOnClickdata-checked, data-unchecked, data-highlighted
RadioGroup/RadioItemvalue/onValueChange (group), value (item)data-checked, data-unchecked
SubmenuTriggeropenOnHover, delay, closeDelaydata-popup-open, data-highlighted
LinkItemlabel, closeOnClickdata-highlighted

Key Takeaways

  1. Never ship an action exclusively behind right-click/long-press — pair every ContextMenu.Item with an equivalent visible button, toolbar action, or menu entry elsewhere.
  2. Reuse Menu knowledge directly here — the item/submenu/radio/checkbox API surface is intentionally identical, only the trigger mechanism (pointer position vs. element) and Root differ.
  3. Use closeParentOnEsc deliberately: default nested-Esc behavior may not match a deeply nested submenu UX — test the multi-level Esc path explicitly.

Connects To

  • ch027 (Menu): shares essentially the entire item/submenu API — read that chapter for any part not covered here.
  • ch008 (Customization): eventDetails cancel/reason pattern applies to onOpenChange here too.