Context Menu

Contextual actions on right-click, with grouped sections, nested submenus, shortcut labels, and destructive items.

Loading preview

Examples

Practical examples and common states for the same installable component.

Grouped

Organizes related actions into labeled sections.

examples/context-menu-grouped.tsx
import {
ContextMenu,
ContextMenuContent,
ContextMenuGroup,
ContextMenuItem,
ContextMenuLabel,
ContextMenuSeparator,
ContextMenuShortcut,
ContextMenuTrigger,
} from "@/components/wensity/context-menu";
import { IconClipboard, IconCopy, IconPencil, IconScissors, IconShare } from "@tabler/icons-react";
export function ContextMenuGrouped() {
return (
<ContextMenu>
<ContextMenuTrigger asChild>
<div className="flex h-28 items-center justify-center rounded-lg border border-dashed">
Right-click this area
</div>
</ContextMenuTrigger>
<ContextMenuContent>
<ContextMenuGroup>
<ContextMenuLabel>Clipboard</ContextMenuLabel>
<ContextMenuItem>
<IconCopy className="size-4" />
Copy
<ContextMenuShortcut>⌘C</ContextMenuShortcut>
</ContextMenuItem>
<ContextMenuItem>
<IconScissors className="size-4" />
Cut
<ContextMenuShortcut>⌘X</ContextMenuShortcut>
</ContextMenuItem>
<ContextMenuItem>
<IconClipboard className="size-4" />
Paste
<ContextMenuShortcut>⌘V</ContextMenuShortcut>
</ContextMenuItem>
</ContextMenuGroup>
<ContextMenuSeparator />
<ContextMenuGroup>
<ContextMenuLabel>Actions</ContextMenuLabel>
<ContextMenuItem>
<IconPencil className="size-4" />
Rename
</ContextMenuItem>
<ContextMenuItem>
<IconShare className="size-4" />
Share
</ContextMenuItem>
</ContextMenuGroup>
</ContextMenuContent>
</ContextMenu>
);
}

Nested

Displays additional actions through submenus.

examples/context-menu-nested.tsx
import {
ContextMenu,
ContextMenuContent,
ContextMenuItem,
ContextMenuSub,
ContextMenuSubContent,
ContextMenuSubTrigger,
ContextMenuTrigger,
} from "@/components/wensity/context-menu";
import { IconDownload, IconLink } from "@tabler/icons-react";
export function ContextMenuNested() {
return (
<ContextMenu>
<ContextMenuTrigger asChild>
<div className="flex h-28 items-center justify-center rounded-lg border border-dashed">
Right-click for submenus
</div>
</ContextMenuTrigger>
<ContextMenuContent>
<ContextMenuItem>
<IconLink className="size-4" />
Copy link
</ContextMenuItem>
<ContextMenuSub>
<ContextMenuSubTrigger>
<IconDownload className="size-4" />
Export as
</ContextMenuSubTrigger>
<ContextMenuSubContent>
<ContextMenuItem>PNG</ContextMenuItem>
<ContextMenuItem>SVG</ContextMenuItem>
<ContextMenuItem>PDF</ContextMenuItem>
</ContextMenuSubContent>
</ContextMenuSub>
</ContextMenuContent>
</ContextMenu>
);
}

Checkbox

Toggles selectable contextual options.

examples/context-menu-checkbox.tsx
import { useState } from "react";
import {
ContextMenu,
ContextMenuCheckboxItem,
ContextMenuContent,
ContextMenuLabel,
ContextMenuTrigger,
} from "@/components/wensity/context-menu";
export function ContextMenuCheckbox() {
const [showGrid, setShowGrid] = useState(true);
const [showRuler, setShowRuler] = useState(false);
return (
<ContextMenu>
<ContextMenuTrigger asChild>
<div className="flex h-28 items-center justify-center rounded-lg border border-dashed">
Right-click to toggle options
</div>
</ContextMenuTrigger>
<ContextMenuContent>
<ContextMenuLabel>View</ContextMenuLabel>
<ContextMenuCheckboxItem checked={showGrid} onCheckedChange={setShowGrid}>
Show grid
</ContextMenuCheckboxItem>
<ContextMenuCheckboxItem checked={showRuler} onCheckedChange={setShowRuler}>
Show ruler
</ContextMenuCheckboxItem>
</ContextMenuContent>
</ContextMenu>
);
}

Radio

Selects one option from a group.

examples/context-menu-radio.tsx
import { useState } from "react";
import {
ContextMenu,
ContextMenuContent,
ContextMenuLabel,
ContextMenuRadioGroup,
ContextMenuRadioItem,
ContextMenuTrigger,
} from "@/components/wensity/context-menu";
export function ContextMenuRadio() {
const [view, setView] = useState("list");
return (
<ContextMenu>
<ContextMenuTrigger asChild>
<div className="flex h-28 items-center justify-center rounded-lg border border-dashed">
Right-click to choose a layout
</div>
</ContextMenuTrigger>
<ContextMenuContent>
<ContextMenuLabel>Layout</ContextMenuLabel>
<ContextMenuRadioGroup value={view} onValueChange={setView}>
<ContextMenuRadioItem value="list">List</ContextMenuRadioItem>
<ContextMenuRadioItem value="grid">Grid</ContextMenuRadioItem>
</ContextMenuRadioGroup>
</ContextMenuContent>
</ContextMenu>
);
}

Destructive

Highlights dangerous or irreversible actions.

examples/context-menu-destructive.tsx
import {
ContextMenu,
ContextMenuContent,
ContextMenuItem,
ContextMenuSeparator,
ContextMenuShortcut,
ContextMenuTrigger,
} from "@/components/wensity/context-menu";
import { IconCopy, IconTrash } from "@tabler/icons-react";
export function ContextMenuDestructive() {
return (
<ContextMenu>
<ContextMenuTrigger asChild>
<div className="flex h-28 items-center justify-center rounded-lg border border-dashed">
Right-click for danger zone
</div>
</ContextMenuTrigger>
<ContextMenuContent>
<ContextMenuItem>
<IconCopy className="size-4" />
Duplicate
</ContextMenuItem>
<ContextMenuSeparator />
<ContextMenuItem destructive>
<IconTrash className="size-4" />
Delete permanently
<ContextMenuShortcut>⌘⌫</ContextMenuShortcut>
</ContextMenuItem>
</ContextMenuContent>
</ContextMenu>
);
}

Props

PropTypeDefaultDescription
openboolean-Controlled open state.
defaultOpenboolean-Initial open state when uncontrolled.
onOpenChange(open: boolean) => void-Called when the menu opens or closes.