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
'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 surfaceInstallation
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>
| Prop | Type | Default | Description |
|---|---|---|---|
inset | boolean | false | Adds pl-8 so the item lines up with checkbox/radio rows. |
variant | "default" | "destructive" | "default" | Switches text and icon color to the destructive token. |
disabled | boolean | false | Disables 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
<ContextMenu>owns the open/close state.<ContextMenuTrigger>wraps the region; right-click anywhere in it opens the menu.<ContextMenuContent>mounts via Portal at the cursor position.- Inside content: same layout vocabulary as
DropdownMenu(items, groups, separators, shortcuts, submenus).
Variations
Submenu, checkbox, and shortcuts
Right-click the region to open a menu that combines shortcuts, a nested ContextMenuSub, a checkbox item, and a destructive action.
'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
Menukey (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
DropdownMenuequivalent. - Role:
role="menu"on content,role="menuitem"on items,role="menuitemcheckbox"androle="menuitemradio"on stateful variants. - Keyboard: arrow keys navigate;
EnterandSpaceactivate; type-ahead jumps to items starting with the typed letter;Esccloses. - 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.
Related
- Dropdown Menu - same compound, triggered by a visible button.
- Popover - non-menu interactive overlay anchored to a trigger.
- Tooltip - hover hint, never a menu.