Capítulo 51 de 108

Context Menu

Core Idea

Menu de ações disparado por clique-direito (desktop) ou long-press (touch). Built on Base UI Context Menu; API praticamente idêntica ao Dropdown Menu.

Key Concepts

  • ContextMenuTrigger: área que responde ao clique-direito/long-press; não é um botão, é o próprio elemento de conteúdo.
  • ContextMenuSub / ContextMenuSubTrigger / ContextMenuSubContent: submenu aninhado (hover/clique abre um segundo painel).
  • ContextMenuCheckboxItem: item com toggle (checked/defaultChecked).
  • ContextMenuRadioGroup / ContextMenuRadioItem: seleção exclusiva, controlado via value/onValueChange.
  • ContextMenuShortcut: exibe hint de atalho de teclado alinhado à direita do item.
  • variant="destructive": em ContextMenuItem, estiliza a ação como perigosa (ex. Delete).
  • side: "top" | "right" | "bottom" | "left" ou lógico "inline-end", controla onde o painel abre relativo ao ponto de clique.
  • pointer-fine: / pointer-coarse:: variantes Tailwind usadas para trocar o texto do trigger entre "Right click" (mouse) e "Long press" (touch).

Code Examples

<ContextMenu>
  <ContextMenuTrigger className="flex aspect-video w-full max-w-xs items-center justify-center rounded-xl border border-dashed text-sm">
    <span className="hidden pointer-fine:inline-block">Right click here</span>
    <span className="hidden pointer-coarse:inline-block">Long press here</span>
  </ContextMenuTrigger>
  <ContextMenuContent className="w-48">
    <ContextMenuGroup>
      <ContextMenuItem>
        Back
        <ContextMenuShortcut>⌘[</ContextMenuShortcut>
      </ContextMenuItem>
      <ContextMenuSub>
        <ContextMenuSubTrigger>More Tools</ContextMenuSubTrigger>
        <ContextMenuSubContent className="w-44">
          <ContextMenuGroup>
            <ContextMenuItem variant="destructive">Delete</ContextMenuItem>
          </ContextMenuGroup>
        </ContextMenuSubContent>
      </ContextMenuSub>
    </ContextMenuGroup>
    <ContextMenuSeparator />
    <ContextMenuGroup>
      <ContextMenuRadioGroup value="pedro">
        <ContextMenuLabel>People</ContextMenuLabel>
        <ContextMenuRadioItem value="pedro">Pedro Duarte</ContextMenuRadioItem>
      </ContextMenuRadioGroup>
    </ContextMenuGroup>
  </ContextMenuContent>
</ContextMenu>
  • O que demonstra: exemplo completo combinando shortcut, submenu, item destrutivo e radio group num único menu.

Reference Tables

Composição:

ContextMenu
├── ContextMenuTrigger
└── ContextMenuContent
    ├── ContextMenuGroup
    │   ├── ContextMenuLabel
    │   ├── ContextMenuItem
    │   └── ContextMenuItem
    ├── ContextMenuSeparator
    ├── ContextMenuGroup (Checkbox items)
    ├── ContextMenuSeparator
    ├── ContextMenuGroup (RadioGroup)
    └── ContextMenuSub
        ├── ContextMenuSubTrigger
        └── ContextMenuSubContent

Anti-patterns

  • Não distinguir mouse vs touch no texto do trigger: usar pointer-fine:/pointer-coarse: para "Right click" vs "Long press", já que touch não tem clique-direito.

Key Takeaways

  1. ContextMenuTrigger envolve a área de conteúdo alvo, não um botão de disparo (diferente de Dropdown Menu).
  2. API é praticamente idêntica ao Dropdown Menu (Group, CheckboxItem, RadioGroup, Sub, Shortcut, variant destructive) — o que se aprende aqui transfere direto.
  3. side="inline-end" posiciona o menu no lado lógico direito, respeitando RTL.
  4. pointer-fine:/pointer-coarse: são as variantes Tailwind recomendadas para adaptar texto/comportamento a mouse vs touch.
  5. Instalação manual requer npm install @base-ui/react.

Connects To

  • Dropdown Menu: mesma família de API (Group, Checkbox, Radio, Sub, Shortcut); Context Menu é acionado por clique-direito, Dropdown por clique normal num trigger visível.
  • Menubar: outro consumidor da mesma família de subcomponentes de menu, mas com barra de menus sempre visível.