Skip to main content
Gremorie

Context Menu

Action menu invoked via right-click on a region. Same compound shape as DropdownMenu, anchored to a target area.

Overview

ContextMenu is a power-user accelerator. Right-click is invisible to users who haven't been taught about it (most touch users; many web users today), so treat this menu as an additive shortcut, never the only path to an action. Every option shown here should also be reachable through a button, DropdownMenu, or keyboard shortcut elsewhere in the UI.

The compound mirrors DropdownMenu exactly: items, groups, separators, submenus, checkbox or radio variants, shortcuts. The only difference is the trigger: ContextMenuTrigger wraps a region, and the menu opens at the cursor position on right-click.

Preview

Right-click here
'use client';import {  ContextMenu,  ContextMenuContent,  ContextMenuItem,  ContextMenuSeparator,  ContextMenuTrigger,} from '@gremorie/rx-overlays';export function ContextMenuPreview() {  return (    <ContextMenu>      <ContextMenuTrigger>        <div className="flex h-32 w-full items-center justify-center rounded-lg border border-dashed text-sm text-muted-foreground">          Right-click here        </div>      </ContextMenuTrigger>      <ContextMenuContent>        <ContextMenuItem>Copy</ContextMenuItem>        <ContextMenuItem>Paste</ContextMenuItem>        <ContextMenuSeparator />        <ContextMenuItem>Delete</ContextMenuItem>      </ContextMenuContent>    </ContextMenu>  );}

Anatomy

ContextMenu                       Radix root, owns open state
├─ ContextMenuTrigger             region that responds to right-click
└─ ContextMenuContent             portalled menu surface
   ├─ ContextMenuGroup            groups related items
   ├─ ContextMenuItem             action row (variant default | destructive, inset)
   │  └─ ContextMenuShortcut      right-aligned keyboard hint
   ├─ ContextMenuCheckboxItem     toggleable item
   ├─ ContextMenuRadioGroup       single-choice container
   │  └─ ContextMenuRadioItem     single-choice item
   ├─ ContextMenuLabel            non-interactive section label
   ├─ ContextMenuSeparator        divider
   └─ ContextMenuSub              nested submenu
      ├─ ContextMenuSubTrigger    row that opens the submenu
      └─ ContextMenuSubContent    nested menu surface

Installation

bash npx gremorie@latest add rx-context-menu

bash pnpm dlx gremorie@latest add rx-context-menu

bash yarn dlx gremorie@latest add rx-context-menu

bash bunx --bun gremorie@latest add rx-context-menu

Usage

import {
  ContextMenu,
  ContextMenuContent,
  ContextMenuItem,
  ContextMenuSeparator,
  ContextMenuTrigger,
} from "@gremorie/rx-overlays";

export function Example() {
  return (
    <ContextMenu>
      <ContextMenuTrigger>
        <div className="flex h-32 w-full items-center justify-center rounded-lg border border-dashed text-sm text-muted-foreground">
          Right-click here
        </div>
      </ContextMenuTrigger>
      <ContextMenuContent>
        <ContextMenuItem>Copy</ContextMenuItem>
        <ContextMenuItem>Paste</ContextMenuItem>
        <ContextMenuSeparator />
        <ContextMenuItem>Delete</ContextMenuItem>
      </ContextMenuContent>
    </ContextMenu>
  );
}

The Angular edition of this component ships from source today (see the workbench for the side-by-side); its registry entry is coming next.

API

<ContextMenu>

Extends Radix ContextMenu.Root. Standard controlled API (onOpenChange, modal).

<ContextMenuTrigger>

Wraps the region that should respond to right-click. By default it renders a <span>; use asChild to forward styles to a target element.

<ContextMenuContent>

Same shape as DropdownMenuContent. Wrapped in a Radix Portal. Positions itself at the cursor on open.

<ContextMenuItem>

PropTypeDefaultDescription
insetbooleanfalseAdds pl-8 so the item lines up with checkbox/radio rows.
variant"default" | "destructive""default"Switches text and icon color to the destructive token.
disabledbooleanfalseDisables interaction; renders at 50% opacity.

<ContextMenuCheckboxItem>, <ContextMenuRadioGroup>, <ContextMenuRadioItem>

Same semantics as their DropdownMenu counterparts. Indicators render automatically in the absolute-positioned left slot.

<ContextMenuLabel>, <ContextMenuSeparator>, <ContextMenuShortcut>

Non-interactive helpers identical to DropdownMenu.

<ContextMenuSub> + <ContextMenuSubTrigger> + <ContextMenuSubContent>

Nested submenu pattern. Sub-trigger renders an auto-positioned chevron.

<ContextMenuPortal>, <ContextMenuGroup>

Pass-throughs over the Radix primitives with data-slot attributes.

Composition

  1. <ContextMenu> owns the open/close state.
  2. <ContextMenuTrigger> wraps the region; right-click anywhere in it opens the menu.
  3. <ContextMenuContent> mounts via Portal at the cursor position.
  4. Inside content: same layout vocabulary as DropdownMenu (items, groups, separators, shortcuts, submenus).

Variations

Right-click the region to open a menu that combines shortcuts, a nested ContextMenuSub, a checkbox item, and a destructive action.

Right-click here
'use client';import { useState } from 'react';import {  ContextMenu,  ContextMenuCheckboxItem,  ContextMenuContent,  ContextMenuItem,  ContextMenuSeparator,  ContextMenuShortcut,  ContextMenuSub,  ContextMenuSubContent,  ContextMenuSubTrigger,  ContextMenuTrigger,} from '@gremorie/rx-overlays';export function ContextMenuSubmenuPreview() {  const [snapToGrid, setSnapToGrid] = useState(true);  return (    <ContextMenu>      <ContextMenuTrigger>        <div className="flex h-32 w-full items-center justify-center rounded-lg border border-dashed text-sm text-muted-foreground">          Right-click here        </div>      </ContextMenuTrigger>      <ContextMenuContent className="w-52">        <ContextMenuItem>          Copy          <ContextMenuShortcut>⌘C</ContextMenuShortcut>        </ContextMenuItem>        <ContextMenuItem>          Paste          <ContextMenuShortcut>⌘V</ContextMenuShortcut>        </ContextMenuItem>        <ContextMenuSub>          <ContextMenuSubTrigger>Move to</ContextMenuSubTrigger>          <ContextMenuSubContent>            <ContextMenuItem>Reports</ContextMenuItem>            <ContextMenuItem>Archive</ContextMenuItem>            <ContextMenuItem>Trash</ContextMenuItem>          </ContextMenuSubContent>        </ContextMenuSub>        <ContextMenuSeparator />        <ContextMenuCheckboxItem          checked={snapToGrid}          onCheckedChange={(checked) => setSnapToGrid(checked === true)}        >          Snap to grid        </ContextMenuCheckboxItem>        <ContextMenuSeparator />        <ContextMenuItem variant="destructive">Delete</ContextMenuItem>      </ContextMenuContent>    </ContextMenu>  );}

File browser actions

Right-click a file row to expose move, rename, and delete.

<ContextMenu>
  <ContextMenuTrigger asChild>
    <tr>
      <td>Report.pdf</td>
      <td>2.4 MB</td>
    </tr>
  </ContextMenuTrigger>
  <ContextMenuContent>
    <ContextMenuItem>Open</ContextMenuItem>
    <ContextMenuItem>Rename</ContextMenuItem>
    <ContextMenuSub>
      <ContextMenuSubTrigger>Move to</ContextMenuSubTrigger>
      <ContextMenuSubContent>
        <ContextMenuItem>Reports</ContextMenuItem>
        <ContextMenuItem>Archive</ContextMenuItem>
      </ContextMenuSubContent>
    </ContextMenuSub>
    <ContextMenuSeparator />
    <ContextMenuItem variant="destructive">Delete</ContextMenuItem>
  </ContextMenuContent>
</ContextMenu>

Canvas tools with shortcuts

Power-user shortcuts in a creative app. Pair every item with its keyboard equivalent.

<ContextMenuContent>
  <ContextMenuItem>
    Copy
    <ContextMenuShortcut>⌘C</ContextMenuShortcut>
  </ContextMenuItem>
  <ContextMenuItem>
    Paste
    <ContextMenuShortcut>⌘V</ContextMenuShortcut>
  </ContextMenuItem>
  <ContextMenuSeparator />
  <ContextMenuCheckboxItem checked={snap}>Snap to grid</ContextMenuCheckboxItem>
</ContextMenuContent>

Per-cell context with radio group

Toggle alignment within a table cell.

<ContextMenuContent>
  <ContextMenuLabel>Align</ContextMenuLabel>
  <ContextMenuSeparator />
  <ContextMenuRadioGroup value={align} onValueChange={setAlign}>
    <ContextMenuRadioItem value="left">Left</ContextMenuRadioItem>
    <ContextMenuRadioItem value="center">Center</ContextMenuRadioItem>
    <ContextMenuRadioItem value="right">Right</ContextMenuRadioItem>
  </ContextMenuRadioGroup>
</ContextMenuContent>

Accessibility

  • Trigger: opens on right-click and on the Menu key (Windows). Long-press is not a standard web gesture, so touch users will not see the menu by default.
  • Additive only: never put an action behind a context menu exclusively. Provide a visible button or DropdownMenu equivalent.
  • Role: role="menu" on content, role="menuitem" on items, role="menuitemcheckbox" and role="menuitemradio" on stateful variants.
  • Keyboard: arrow keys navigate; Enter and Space activate; type-ahead jumps to items starting with the typed letter; Esc closes.
  • Submenus: opens, closes.
  • Focus management: focus moves into the menu on open and returns to the trigger region on close.
  • Reduced motion: open/close animations honor prefers-reduced-motion.
  • Dropdown Menu - same compound, triggered by a visible button.
  • Popover - non-menu interactive overlay anchored to a trigger.
  • Tooltip - hover hint, never a menu.

On this page