ContextMenu

A menu triggered by a right-click (or long-press on touch) that surfaces contextual actions for the element under the cursor. Built on @base-ui/react/menu with full keyboard navigation and ARIA menu role.

Anatomy

<ContextMenu> is the stateful root. ContextMenuTrigger wraps the element that should respond to right-click. ContextMenuContent renders in a portal at the cursor position. ContextMenuItem is an action row. ContextMenuLabel adds a non-interactive heading. ContextMenuSeparator draws a divider. ContextMenuShortcut displays a keyboard hint aligned to the right.

Right-click here
ContextMenuTrigger (right-click zone)ContextMenuContent (portal at cursor)

Examples

Text editor actions

Right-click for text actions

File actions

document.pdf

Design Guidelines

Do

  • Mirror keyboard shortcuts. If an action has a shortcut (Cut: ⌘X), show it in the menu with ContextMenuShortcut — it reinforces discoverability.
  • Surface only context-relevant actions. The menu should adapt to what the user right-clicked — a text selection menu differs from a file menu.
  • Place destructive items last. Separate delete/remove actions below a ContextMenuSeparatorso users don't trigger them accidentally.

Don't

  • Don't rely on it as the only path. Context menus are hidden by default — critical actions must also be reachable via visible UI elements.
  • Don't use for primary navigation. Context menus are for actions on selected content, not for moving between pages or sections.
  • Don't show irrelevant items. Rendering greyed-out or disabled items for the current context adds noise — hide them instead.

Developer Reference

Accessibility

  • ContextMenuContent has role="menu"; each ContextMenuItem has role="menuitem".
  • The menu opens at the cursor position on right-click, or at the element's position on keyboard (Shift+F10 or the Menu key).
  • Arrow keys navigate items. Enter / Space activate. ESC closes and returns focus to the trigger.
  • ContextMenuTrigger can wrap any element — it adds a contextmenuevent listener without altering the element's semantics.

Usage

import {
  ContextMenu,
  ContextMenuTrigger,
  ContextMenuContent,
  ContextMenuItem,
  ContextMenuGroup,
  ContextMenuLabel,
  ContextMenuSeparator,
  ContextMenuShortcut,
} from "@/components/ui/context-menu"

<ContextMenu>
  <ContextMenuTrigger className="flex h-32 w-full items-center justify-center rounded-lg border border-dashed">
    Right-click here
  </ContextMenuTrigger>
  <ContextMenuContent>
    <ContextMenuGroup>
      <ContextMenuLabel>Actions</ContextMenuLabel>
      <ContextMenuSeparator />
      <ContextMenuItem>
        Copy
        <ContextMenuShortcut>⌘C</ContextMenuShortcut>
      </ContextMenuItem>
      <ContextMenuItem>
        Paste
        <ContextMenuShortcut>⌘V</ContextMenuShortcut>
      </ContextMenuItem>
    </ContextMenuGroup>
    <ContextMenuSeparator />
    <ContextMenuItem className="text-destructive focus:text-destructive">
      Delete
    </ContextMenuItem>
  </ContextMenuContent>
</ContextMenu>