Context Menu
Displays a menu of actions triggered by a right click.
Right-click the resume card
"use client"
import { Copy, Download, Pencil, Trash2 } from "lucide-react"
import {
ContextMenu,
ContextMenuCheckboxItem,
ContextMenuContent,
ContextMenuGroup,
ContextMenuItem,
ContextMenuLabel,
ContextMenuRadioGroup,
ContextMenuRadioItem,
ContextMenuSeparator,
ContextMenuShortcut,
ContextMenuSub,
ContextMenuSubContent,
ContextMenuSubTrigger,
ContextMenuTrigger,
} from "@/components/ui/context-menu"
const contextTemplateOptions = ["Modern", "Timeline", "Executive"] as const
export default function ContextMenuDemo() {
return (
<ContextMenu>
<ContextMenuTrigger className="grid h-24 w-full place-items-center rounded-md border border-dashed border-border text-sm text-muted-foreground">
Right-click the resume card
</ContextMenuTrigger>
<ContextMenuContent className="w-56">
<ContextMenuGroup>
<ContextMenuLabel>Senior Software Engineer</ContextMenuLabel>
<ContextMenuItem>
<Pencil /> Rename <ContextMenuShortcut>⌘R</ContextMenuShortcut>
</ContextMenuItem>
<ContextMenuItem>
<Copy /> Duplicate <ContextMenuShortcut>⌘D</ContextMenuShortcut>
</ContextMenuItem>
<ContextMenuSub>
<ContextMenuSubTrigger>
<Download /> Export as
</ContextMenuSubTrigger>
<ContextMenuSubContent>
<ContextMenuGroup>
<ContextMenuItem>PDF</ContextMenuItem>
<ContextMenuItem>Word (.docx)</ContextMenuItem>
<ContextMenuItem>Plain text</ContextMenuItem>
</ContextMenuGroup>
</ContextMenuSubContent>
</ContextMenuSub>
</ContextMenuGroup>
<ContextMenuSeparator />
<ContextMenuGroup>
<ContextMenuCheckboxItem defaultChecked>
Public share link
</ContextMenuCheckboxItem>
</ContextMenuGroup>
<ContextMenuSeparator />
<ContextMenuGroup>
<ContextMenuLabel>Template</ContextMenuLabel>
<ContextMenuRadioGroup defaultValue="Modern">
{contextTemplateOptions.map((t) => (
<ContextMenuRadioItem key={t} value={t}>
{t}
</ContextMenuRadioItem>
))}
</ContextMenuRadioGroup>
</ContextMenuGroup>
<ContextMenuSeparator />
<ContextMenuGroup>
<ContextMenuItem variant="destructive">
<Trash2 /> Delete <ContextMenuShortcut>⌫</ContextMenuShortcut>
</ContextMenuItem>
</ContextMenuGroup>
</ContextMenuContent>
</ContextMenu>
)
}Installation
pnpm dlx shadcn@latest add @kickresume/context-menuUsage
import { ContextMenu, ContextMenuTrigger, ContextMenuContent, ContextMenuItem, ContextMenuCheckboxItem, ContextMenuRadioItem, ContextMenuLabel, ContextMenuSeparator, ContextMenuShortcut, ContextMenuGroup, ContextMenuPortal, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuRadioGroup } from "@/components/ui/context-menu"<ContextMenu>
<ContextMenuTrigger className="grid h-24 w-full place-items-center rounded-md border border-dashed border-border text-sm text-muted-foreground">
Right-click the resume card
</ContextMenuTrigger>
<ContextMenuContent className="w-56">
<ContextMenuGroup>
<ContextMenuLabel>Senior Software Engineer</ContextMenuLabel>
<ContextMenuItem>
<Pencil /> Rename <ContextMenuShortcut>⌘R</ContextMenuShortcut>
</ContextMenuItem>
<ContextMenuItem>
<Copy /> Duplicate <ContextMenuShortcut>⌘D</ContextMenuShortcut>
</ContextMenuItem>
<ContextMenuSub>
<ContextMenuSubTrigger>
<Download /> Export as
</ContextMenuSubTrigger>
<ContextMenuSubContent>
<ContextMenuGroup>
<ContextMenuItem>PDF</ContextMenuItem>
<ContextMenuItem>Word (.docx)</ContextMenuItem>
<ContextMenuItem>Plain text</ContextMenuItem>
</ContextMenuGroup>
</ContextMenuSubContent>
</ContextMenuSub>
</ContextMenuGroup>
<ContextMenuSeparator />
<ContextMenuGroup>
<ContextMenuCheckboxItem defaultChecked>
Public share link
</ContextMenuCheckboxItem>
</ContextMenuGroup>
<ContextMenuSeparator />
<ContextMenuGroup>
<ContextMenuLabel>Template</ContextMenuLabel>
<ContextMenuRadioGroup defaultValue="Modern">
{contextTemplateOptions.map((t) => (
<ContextMenuRadioItem key={t} value={t}>
{t}
</ContextMenuRadioItem>
))}
</ContextMenuRadioGroup>
</ContextMenuGroup>
<ContextMenuSeparator />
<ContextMenuGroup>
<ContextMenuItem variant="destructive">
<Trash2 /> Delete <ContextMenuShortcut>⌫</ContextMenuShortcut>
</ContextMenuItem>
</ContextMenuGroup>
</ContextMenuContent>
</ContextMenu>Composition
Use the following composition to build a ContextMenu:
ContextMenu
├── ContextMenuTrigger
└── ContextMenuContent
├── ContextMenuGroup
│ ├── ContextMenuLabel
│ ├── ContextMenuItem
│ └── ContextMenuItem
├── ContextMenuSeparator
├── ContextMenuGroup
│ ├── ContextMenuLabel
│ ├── ContextMenuCheckboxItem
│ └── ContextMenuCheckboxItem
├── ContextMenuSeparator
├── ContextMenuGroup
│ ├── ContextMenuLabel
│ └── ContextMenuRadioGroup
│ ├── ContextMenuRadioItem
│ └── ContextMenuRadioItem
└── ContextMenuSub
├── ContextMenuSubTrigger
└── ContextMenuSubContent
└── ContextMenuGroup
├── ContextMenuItem
└── ContextMenuItemExamples
Basic
A simple context menu with a few actions.
Right click here
"use client"
import {
ContextMenu,
ContextMenuContent,
ContextMenuGroup,
ContextMenuItem,
ContextMenuTrigger,
} from "@/components/ui/context-menu"
export default function ContextMenuBasic() {
return (
<ContextMenu>
<ContextMenuTrigger className="grid h-24 w-full max-w-sm place-items-center rounded-md border border-dashed border-border text-sm text-muted-foreground">
Right click here
</ContextMenuTrigger>
<ContextMenuContent className="w-48">
<ContextMenuGroup>
<ContextMenuItem>Open</ContextMenuItem>
<ContextMenuItem disabled>Duplicate</ContextMenuItem>
<ContextMenuItem>Download</ContextMenuItem>
</ContextMenuGroup>
</ContextMenuContent>
</ContextMenu>
)
}Submenu
Use ContextMenuSub to nest secondary actions.
Right click here
"use client"
import {
ContextMenu,
ContextMenuContent,
ContextMenuGroup,
ContextMenuItem,
ContextMenuSeparator,
ContextMenuSub,
ContextMenuSubContent,
ContextMenuSubTrigger,
ContextMenuTrigger,
} from "@/components/ui/context-menu"
export default function ContextMenuSubmenu() {
return (
<ContextMenu>
<ContextMenuTrigger className="grid h-24 w-full max-w-sm place-items-center rounded-md border border-dashed border-border text-sm text-muted-foreground">
Right click here
</ContextMenuTrigger>
<ContextMenuContent className="w-52">
<ContextMenuGroup>
<ContextMenuItem>Rename</ContextMenuItem>
<ContextMenuItem>Add to favorites</ContextMenuItem>
<ContextMenuSub>
<ContextMenuSubTrigger>Move to</ContextMenuSubTrigger>
<ContextMenuSubContent>
<ContextMenuGroup>
<ContextMenuItem>Applications</ContextMenuItem>
<ContextMenuItem>Drafts</ContextMenuItem>
<ContextMenuItem>Archived</ContextMenuItem>
</ContextMenuGroup>
<ContextMenuSeparator />
<ContextMenuGroup>
<ContextMenuItem>New folder…</ContextMenuItem>
</ContextMenuGroup>
</ContextMenuSubContent>
</ContextMenuSub>
</ContextMenuGroup>
</ContextMenuContent>
</ContextMenu>
)
}Shortcuts
Add ContextMenuShortcut to show keyboard hints.
Right click here
"use client"
import {
ContextMenu,
ContextMenuContent,
ContextMenuGroup,
ContextMenuItem,
ContextMenuSeparator,
ContextMenuShortcut,
ContextMenuTrigger,
} from "@/components/ui/context-menu"
export default function ContextMenuShortcuts() {
return (
<ContextMenu>
<ContextMenuTrigger className="grid h-24 w-full max-w-sm place-items-center rounded-md border border-dashed border-border text-sm text-muted-foreground">
Right click here
</ContextMenuTrigger>
<ContextMenuContent>
<ContextMenuGroup>
<ContextMenuItem>
Undo
<ContextMenuShortcut>⌘Z</ContextMenuShortcut>
</ContextMenuItem>
<ContextMenuItem disabled>
Redo
<ContextMenuShortcut>⇧⌘Z</ContextMenuShortcut>
</ContextMenuItem>
<ContextMenuItem>
Rephrase with AI
<ContextMenuShortcut>⌘J</ContextMenuShortcut>
</ContextMenuItem>
</ContextMenuGroup>
<ContextMenuSeparator />
<ContextMenuGroup>
<ContextMenuItem>
Save
<ContextMenuShortcut>⌘S</ContextMenuShortcut>
</ContextMenuItem>
<ContextMenuItem>
Save As…
<ContextMenuShortcut>⇧⌘S</ContextMenuShortcut>
</ContextMenuItem>
</ContextMenuGroup>
</ContextMenuContent>
</ContextMenu>
)
}Groups
Group related actions and separate them with dividers.
Right click here
"use client"
import {
ContextMenu,
ContextMenuContent,
ContextMenuGroup,
ContextMenuItem,
ContextMenuLabel,
ContextMenuSeparator,
ContextMenuShortcut,
ContextMenuTrigger,
} from "@/components/ui/context-menu"
export default function ContextMenuGroups() {
return (
<ContextMenu>
<ContextMenuTrigger className="grid h-24 w-full max-w-sm place-items-center rounded-md border border-dashed border-border text-sm text-muted-foreground">
Right click here
</ContextMenuTrigger>
<ContextMenuContent>
<ContextMenuGroup>
<ContextMenuLabel>File</ContextMenuLabel>
<ContextMenuItem>
New resume
<ContextMenuShortcut>⌘N</ContextMenuShortcut>
</ContextMenuItem>
<ContextMenuItem>
New cover letter
<ContextMenuShortcut>⌘L</ContextMenuShortcut>
</ContextMenuItem>
<ContextMenuItem>
Save
<ContextMenuShortcut>⌘S</ContextMenuShortcut>
</ContextMenuItem>
</ContextMenuGroup>
<ContextMenuSeparator />
<ContextMenuGroup>
<ContextMenuLabel>Edit</ContextMenuLabel>
<ContextMenuItem>
Undo
<ContextMenuShortcut>⌘Z</ContextMenuShortcut>
</ContextMenuItem>
<ContextMenuItem>
Redo
<ContextMenuShortcut>⇧⌘Z</ContextMenuShortcut>
</ContextMenuItem>
</ContextMenuGroup>
<ContextMenuSeparator />
<ContextMenuGroup>
<ContextMenuItem>
Cut
<ContextMenuShortcut>⌘X</ContextMenuShortcut>
</ContextMenuItem>
<ContextMenuItem>
Copy
<ContextMenuShortcut>⌘C</ContextMenuShortcut>
</ContextMenuItem>
<ContextMenuItem>
Paste
<ContextMenuShortcut>⌘V</ContextMenuShortcut>
</ContextMenuItem>
</ContextMenuGroup>
<ContextMenuSeparator />
<ContextMenuGroup>
<ContextMenuItem variant="destructive">
Delete
<ContextMenuShortcut>⌫</ContextMenuShortcut>
</ContextMenuItem>
</ContextMenuGroup>
</ContextMenuContent>
</ContextMenu>
)
}Icons
Combine icons with labels for quick scanning.
Right click here
"use client"
import { Copy, Download, Pencil, Trash2 } from "lucide-react"
import {
ContextMenu,
ContextMenuContent,
ContextMenuGroup,
ContextMenuItem,
ContextMenuSeparator,
ContextMenuTrigger,
} from "@/components/ui/context-menu"
export default function ContextMenuIcons() {
return (
<ContextMenu>
<ContextMenuTrigger className="grid h-24 w-full max-w-sm place-items-center rounded-md border border-dashed border-border text-sm text-muted-foreground">
Right click here
</ContextMenuTrigger>
<ContextMenuContent>
<ContextMenuGroup>
<ContextMenuItem>
<Pencil />
Rename
</ContextMenuItem>
<ContextMenuItem>
<Copy />
Duplicate
</ContextMenuItem>
<ContextMenuItem>
<Download />
Download
</ContextMenuItem>
</ContextMenuGroup>
<ContextMenuSeparator />
<ContextMenuGroup>
<ContextMenuItem variant="destructive">
<Trash2 />
Delete
</ContextMenuItem>
</ContextMenuGroup>
</ContextMenuContent>
</ContextMenu>
)
}Checkboxes
Use ContextMenuCheckboxItem for toggles.
Right click here
"use client"
import {
ContextMenu,
ContextMenuCheckboxItem,
ContextMenuContent,
ContextMenuGroup,
ContextMenuTrigger,
} from "@/components/ui/context-menu"
export default function ContextMenuCheckboxes() {
return (
<ContextMenu>
<ContextMenuTrigger className="grid h-24 w-full max-w-sm place-items-center rounded-md border border-dashed border-border text-sm text-muted-foreground">
Right click here
</ContextMenuTrigger>
<ContextMenuContent>
<ContextMenuGroup>
<ContextMenuCheckboxItem defaultChecked>
Show ATS score
</ContextMenuCheckboxItem>
<ContextMenuCheckboxItem>Public share link</ContextMenuCheckboxItem>
<ContextMenuCheckboxItem defaultChecked>
Auto-save drafts
</ContextMenuCheckboxItem>
</ContextMenuGroup>
</ContextMenuContent>
</ContextMenu>
)
}Radio
Use ContextMenuRadioItem for exclusive choices.
Right click here
"use client"
import * as React from "react"
import {
ContextMenu,
ContextMenuContent,
ContextMenuGroup,
ContextMenuLabel,
ContextMenuRadioGroup,
ContextMenuRadioItem,
ContextMenuSeparator,
ContextMenuTrigger,
} from "@/components/ui/context-menu"
const contextTemplateOptions = ["Modern", "Timeline", "Executive"] as const
export default function ContextMenuRadio() {
const [template, setTemplate] = React.useState("Modern")
const [theme, setTheme] = React.useState("light")
return (
<ContextMenu>
<ContextMenuTrigger className="grid h-24 w-full max-w-sm place-items-center rounded-md border border-dashed border-border text-sm text-muted-foreground">
Right click here
</ContextMenuTrigger>
<ContextMenuContent>
<ContextMenuGroup>
<ContextMenuLabel>Template</ContextMenuLabel>
<ContextMenuRadioGroup value={template} onValueChange={setTemplate}>
{contextTemplateOptions.map((option) => (
<ContextMenuRadioItem key={option} value={option}>
{option}
</ContextMenuRadioItem>
))}
</ContextMenuRadioGroup>
</ContextMenuGroup>
<ContextMenuSeparator />
<ContextMenuGroup>
<ContextMenuLabel>Theme</ContextMenuLabel>
<ContextMenuRadioGroup value={theme} onValueChange={setTheme}>
<ContextMenuRadioItem value="light">Light</ContextMenuRadioItem>
<ContextMenuRadioItem value="dark">Dark</ContextMenuRadioItem>
<ContextMenuRadioItem value="system">System</ContextMenuRadioItem>
</ContextMenuRadioGroup>
</ContextMenuGroup>
</ContextMenuContent>
</ContextMenu>
)
}Destructive
Use variant="destructive" to style the menu item as destructive.
Right click here
"use client"
import { Archive, Pencil, Share2, Trash2 } from "lucide-react"
import {
ContextMenu,
ContextMenuContent,
ContextMenuGroup,
ContextMenuItem,
ContextMenuSeparator,
ContextMenuTrigger,
} from "@/components/ui/context-menu"
export default function ContextMenuDestructive() {
return (
<ContextMenu>
<ContextMenuTrigger className="grid h-24 w-full max-w-sm place-items-center rounded-md border border-dashed border-border text-sm text-muted-foreground">
Right click here
</ContextMenuTrigger>
<ContextMenuContent>
<ContextMenuGroup>
<ContextMenuItem>
<Pencil />
Edit
</ContextMenuItem>
<ContextMenuItem>
<Share2 />
Share
</ContextMenuItem>
<ContextMenuItem>
<Archive />
Archive
</ContextMenuItem>
</ContextMenuGroup>
<ContextMenuSeparator />
<ContextMenuGroup>
<ContextMenuItem variant="destructive">
<Trash2 />
Delete
</ContextMenuItem>
</ContextMenuGroup>
</ContextMenuContent>
</ContextMenu>
)
}Sides
Control submenu placement with side and align props.
Loading…
"use client"
import {
ContextMenu,
ContextMenuContent,
ContextMenuGroup,
ContextMenuItem,
ContextMenuTrigger,
} from "@/components/ui/context-menu"
const sides = ["top", "right", "bottom", "left"] as const
export default function ContextMenuSides() {
return (
<div className="grid w-full max-w-sm grid-cols-2 gap-4">
{sides.map((side) => (
<ContextMenu key={side}>
<ContextMenuTrigger className="grid h-24 place-items-center rounded-md border border-dashed border-border text-sm text-muted-foreground capitalize">
{side}
</ContextMenuTrigger>
<ContextMenuContent side={side}>
<ContextMenuGroup>
<ContextMenuItem>Open</ContextMenuItem>
<ContextMenuItem>Rename</ContextMenuItem>
<ContextMenuItem>Download</ContextMenuItem>
</ContextMenuGroup>
</ContextMenuContent>
</ContextMenu>
))}
</div>
)
}API Reference
See the Base UI documentation for more information.