Context menu
A menu that opens on right click or long press, with the same items, shortcuts and variants as Dropdown menu.
npx prodular-ui add context-menuFile actions
Right click the row. Shortcuts line up on the right.
Q4 board update.pdf2.4 MB, edited by Tom BeckerRight click
import { CopyIcon, DownloadIcon, FileTextIcon, FolderInputIcon, PencilIcon, StarIcon, Trash2Icon,} from "lucide-react"
import { ContextMenu, ContextMenuContent, ContextMenuItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger,} from "@/components/ui/context-menu"
export default function ContextMenuFile() { return ( <ContextMenu> <ContextMenuTrigger className="flex w-full max-w-sm items-center gap-3 rounded-xl border border-dashed border-border-strong px-4 py-5 text-sm"> <FileTextIcon className="size-5 text-muted-foreground" /> <span className="flex min-w-0 flex-1 flex-col"> <span className="truncate font-medium">Q4 board update.pdf</span> <span className="text-xs text-muted-foreground">2.4 MB, edited by Tom Becker</span> </span> <span className="text-xs text-muted-foreground">Right click</span> </ContextMenuTrigger> <ContextMenuContent className="w-56"> <ContextMenuItem> <PencilIcon /> Rename <ContextMenuShortcut>F2</ContextMenuShortcut> </ContextMenuItem> <ContextMenuItem> <CopyIcon /> Duplicate <ContextMenuShortcut>⌘D</ContextMenuShortcut> </ContextMenuItem> <ContextMenuItem> <StarIcon /> Add to favorites </ContextMenuItem> <ContextMenuSub> <ContextMenuSubTrigger> <FolderInputIcon /> Move to </ContextMenuSubTrigger> <ContextMenuSubContent> <ContextMenuItem>Board meetings</ContextMenuItem> <ContextMenuItem>Finance</ContextMenuItem> <ContextMenuItem>Shared with me</ContextMenuItem> </ContextMenuSubContent> </ContextMenuSub> <ContextMenuItem> <DownloadIcon /> Download </ContextMenuItem> <ContextMenuSeparator /> <ContextMenuItem variant="destructive"> <Trash2Icon /> Move to trash <ContextMenuShortcut>⌘⌫</ContextMenuShortcut> </ContextMenuItem> </ContextMenuContent> </ContextMenu> )}Checkbox and radio items
Right click the canvas
"use client"
import * as React from "react"
import { ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuLabel, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuTrigger,} from "@/components/ui/context-menu"
export default function ContextMenuCanvas() { const [grid, setGrid] = React.useState(true) const [rulers, setRulers] = React.useState(false) const [zoom, setZoom] = React.useState("fit") return ( <ContextMenu> <ContextMenuTrigger className="flex h-44 w-full max-w-md items-center justify-center rounded-xl border border-dashed border-border-strong text-sm text-muted-foreground"> Right click the canvas </ContextMenuTrigger> <ContextMenuContent className="w-52"> <ContextMenuGroup> <ContextMenuLabel>View</ContextMenuLabel> <ContextMenuCheckboxItem checked={grid} onCheckedChange={setGrid}> Show grid </ContextMenuCheckboxItem> <ContextMenuCheckboxItem checked={rulers} onCheckedChange={setRulers}> Show rulers </ContextMenuCheckboxItem> </ContextMenuGroup> <ContextMenuSeparator /> <ContextMenuGroup> <ContextMenuLabel>Zoom</ContextMenuLabel> <ContextMenuRadioGroup value={zoom} onValueChange={setZoom}> <ContextMenuRadioItem value="fit">Zoom to fit</ContextMenuRadioItem> <ContextMenuRadioItem value="50">50%</ContextMenuRadioItem> <ContextMenuRadioItem value="100">100%</ContextMenuRadioItem> <ContextMenuRadioItem value="200">200%</ContextMenuRadioItem> </ContextMenuRadioGroup> </ContextMenuGroup> </ContextMenuContent> </ContextMenu> )}Anatomy
<ContextMenu> <ContextMenuTrigger className="rounded-xl border border-dashed p-6">Q4 board update.pdf</ContextMenuTrigger> <ContextMenuContent className="w-56"> <ContextMenuItem> <PencilIcon /> Rename <ContextMenuShortcut>F2</ContextMenuShortcut> </ContextMenuItem> <ContextMenuSeparator /> <ContextMenuItem variant="destructive"> <Trash2Icon /> Move to trash </ContextMenuItem> </ContextMenuContent></ContextMenu>Guidance
Use it when
- Use on dense surfaces where right click is expected: file lists, tables, canvases, editors.
- Mirror the actions from the object's visible menu button so mouse users find them in both places.
Avoid
- Being the only way to reach an action. Touch and keyboard users may never open it.
- Menus on plain text or links, where the browser menu is more useful.
Rules for AI agents
Published in llms-full.txt, the registry and the MCP server, so coding agents follow them when they build with this component.
- Give every item a verb or a destination as its label. Put the icon first, then the label, then ContextMenuShortcut.
- Use variant="destructive" on the item that deletes or signs out, and put it last, after a separator.
- Group related items with ContextMenuGroup and a ContextMenuLabel in sentence case. Labels must be inside a group.
- Icons are 16px and muted automatically. Do not add size or color classes to them.
- Wrap the target area in ContextMenuTrigger. It renders a div, so pass layout classes to it directly.
- Every action in a context menu must also be reachable from a visible button or a keyboard shortcut.
API
ContextMenuItem
| Prop | Type | Default | Description |
|---|---|---|---|
| variant | "default" | "destructive" | "default" | destructive colors the item and its hover state. |
| inset | boolean | false | Indents the label to line up with items that have icons. |
ContextMenuContent
| Prop | Type | Default | Description |
|---|---|---|---|
| alignOffset / sideOffset | number | 4 / 0 | Offset from the pointer. |
Installation
The Prodular UI CLI adds the source to components/ui with everything it depends on. In a project that already uses shadcn/ui, the shadcn CLI installs it from the Prodular registry too. See Installation for the first setup.
npx prodular-ui add context-menu# or, with the registry in components.jsonnpx shadcn@latest add @prodular/context-menu