Right click here
Installation

pnpm dlx shadcn@latest add @cortexcn/context-menuUsage
import { ContextMenu, ContextMenuTrigger, ContextMenuContent, ContextMenuItem, ContextMenuCheckboxItem, ContextMenuRadioItem, ContextMenuLabel, ContextMenuSeparator, ContextMenuShortcut, ContextMenuGroup, ContextMenuPortal, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuRadioGroup } from "@/components/context-menu";Examples
Basic
Right click here
import { ContextMenu, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuTrigger } from "@/components/context-menu"export function ContextMenuBasic() { return ( <div className="flex flex-col gap-6"> <ContextMenu> <ContextMenuTrigger className="flex aspect-[2/0.5] w-full items-center justify-center rounded-lg border text-sm"> Right click here </ContextMenuTrigger> <ContextMenuContent> <ContextMenuGroup> <ContextMenuItem>Back</ContextMenuItem> <ContextMenuItem disabled>Forward</ContextMenuItem> <ContextMenuItem>Reload</ContextMenuItem> </ContextMenuGroup> </ContextMenuContent> </ContextMenu> </div> )}With sides
Right click (top)Right click (right)Right click (bottom)Right click (left)
import { ContextMenu, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuTrigger } from "@/components/context-menu"export function ContextMenuWithSides() { return ( <div className="flex flex-col gap-6"> <div className="grid grid-cols-2 gap-6"> <ContextMenu> <ContextMenuTrigger className="flex aspect-[2/0.5] w-full items-center justify-center rounded-lg border text-sm"> Right click (top) </ContextMenuTrigger> <ContextMenuContent side="top"> <ContextMenuGroup> <ContextMenuItem>Back</ContextMenuItem> <ContextMenuItem>Forward</ContextMenuItem> <ContextMenuItem>Reload</ContextMenuItem> </ContextMenuGroup> </ContextMenuContent> </ContextMenu> <ContextMenu> <ContextMenuTrigger className="flex aspect-[2/0.5] w-full items-center justify-center rounded-lg border text-sm"> Right click (right) </ContextMenuTrigger> <ContextMenuContent side="right"> <ContextMenuGroup> <ContextMenuItem>Back</ContextMenuItem> <ContextMenuItem>Forward</ContextMenuItem> <ContextMenuItem>Reload</ContextMenuItem> </ContextMenuGroup> </ContextMenuContent> </ContextMenu> <ContextMenu> <ContextMenuTrigger className="flex aspect-[2/0.5] w-full items-center justify-center rounded-lg border text-sm"> Right click (bottom) </ContextMenuTrigger> <ContextMenuContent side="bottom"> <ContextMenuGroup> <ContextMenuItem>Back</ContextMenuItem> <ContextMenuItem>Forward</ContextMenuItem> <ContextMenuItem>Reload</ContextMenuItem> </ContextMenuGroup> </ContextMenuContent> </ContextMenu> <ContextMenu> <ContextMenuTrigger className="flex aspect-[2/0.5] w-full items-center justify-center rounded-lg border text-sm"> Right click (left) </ContextMenuTrigger> <ContextMenuContent side="left"> <ContextMenuGroup> <ContextMenuItem>Back</ContextMenuItem> <ContextMenuItem>Forward</ContextMenuItem> <ContextMenuItem>Reload</ContextMenuItem> </ContextMenuGroup> </ContextMenuContent> </ContextMenu> </div> </div> )}With icons
Right click here
import { ContextMenu, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuSeparator, ContextMenuTrigger } from "@/components/context-menu"import { ClipboardPasteIcon, CopyIcon, ScissorsIcon, TrashIcon } from "lucide-react"export function ContextMenuWithIcons() { return ( <div className="flex flex-col gap-6"> <ContextMenu> <ContextMenuTrigger className="flex aspect-[2/0.5] w-full items-center justify-center rounded-lg border text-sm"> Right click here </ContextMenuTrigger> <ContextMenuContent> <ContextMenuGroup> <ContextMenuItem> <CopyIcon /> Copy </ContextMenuItem> <ContextMenuItem> <ScissorsIcon /> Cut </ContextMenuItem> <ContextMenuItem> <ClipboardPasteIcon /> Paste </ContextMenuItem> </ContextMenuGroup> <ContextMenuSeparator /> <ContextMenuGroup> <ContextMenuItem variant="destructive"> <TrashIcon /> Delete </ContextMenuItem> </ContextMenuGroup> </ContextMenuContent> </ContextMenu> </div> )}With shortcuts
Right click here
import { ContextMenu, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuTrigger } from "@/components/context-menu"export function ContextMenuWithShortcuts() { return ( <div className="flex flex-col gap-6"> <ContextMenu> <ContextMenuTrigger className="flex aspect-[2/0.5] w-full items-center justify-center rounded-lg border text-sm"> Right click here </ContextMenuTrigger> <ContextMenuContent> <ContextMenuGroup> <ContextMenuItem> Back <ContextMenuShortcut>⌘[</ContextMenuShortcut> </ContextMenuItem> <ContextMenuItem disabled> Forward <ContextMenuShortcut>⌘]</ContextMenuShortcut> </ContextMenuItem> <ContextMenuItem> Reload <ContextMenuShortcut>⌘R</ContextMenuShortcut> </ContextMenuItem> </ContextMenuGroup> <ContextMenuSeparator /> <ContextMenuGroup> <ContextMenuItem> Save <ContextMenuShortcut>⌘S</ContextMenuShortcut> </ContextMenuItem> <ContextMenuItem> Save As... <ContextMenuShortcut>⇧⌘S</ContextMenuShortcut> </ContextMenuItem> </ContextMenuGroup> </ContextMenuContent> </ContextMenu> </div> )}With submenu
Right click here
import { ContextMenu, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger } from "@/components/context-menu"export function ContextMenuWithSubmenu() { return ( <div className="flex flex-col gap-6"> <ContextMenu> <ContextMenuTrigger className="flex aspect-[2/0.5] w-full items-center justify-center rounded-lg border text-sm"> Right click here </ContextMenuTrigger> <ContextMenuContent> <ContextMenuGroup> <ContextMenuItem> Copy <ContextMenuShortcut>⌘C</ContextMenuShortcut> </ContextMenuItem> <ContextMenuItem> Cut <ContextMenuShortcut>⌘X</ContextMenuShortcut> </ContextMenuItem> </ContextMenuGroup> <ContextMenuSub> <ContextMenuSubTrigger>More Tools</ContextMenuSubTrigger> <ContextMenuSubContent> <ContextMenuGroup> <ContextMenuItem>Save Page...</ContextMenuItem> <ContextMenuItem>Create Shortcut...</ContextMenuItem> <ContextMenuItem>Name Window...</ContextMenuItem> </ContextMenuGroup> <ContextMenuSeparator /> <ContextMenuGroup> <ContextMenuItem>Developer Tools</ContextMenuItem> </ContextMenuGroup> <ContextMenuSeparator /> <ContextMenuGroup> <ContextMenuItem variant="destructive">Delete</ContextMenuItem> </ContextMenuGroup> </ContextMenuSubContent> </ContextMenuSub> </ContextMenuContent> </ContextMenu> </div> )}With groups, labels and separators
Right click here
import { ContextMenu, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuSeparator, ContextMenuShortcut, ContextMenuTrigger } from "@/components/context-menu"export function ContextMenuWithGroups() { return ( <div className="flex flex-col gap-6"> <ContextMenu> <ContextMenuTrigger className="flex aspect-[2/0.5] w-full items-center justify-center rounded-lg border text-sm"> Right click here </ContextMenuTrigger> <ContextMenuContent> <ContextMenuGroup> <ContextMenuLabel>File</ContextMenuLabel> <ContextMenuItem> New File <ContextMenuShortcut>⌘N</ContextMenuShortcut> </ContextMenuItem> <ContextMenuItem> Open File <ContextMenuShortcut>⌘O</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> <ContextMenuSeparator /> <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> </div> )}With checkboxes
Right click here
import * as React from "react"import { ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuTrigger } from "@/components/context-menu"export function ContextMenuWithCheckboxes() { const [showBookmarksBar, setShowBookmarksBar] = React.useState(true) const [showFullUrls, setShowFullUrls] = React.useState(false) const [showDeveloperTools, setShowDeveloperTools] = React.useState(false) return ( <div className="flex flex-col gap-6"> <ContextMenu> <ContextMenuTrigger className="flex aspect-[2/0.5] w-full items-center justify-center rounded-lg border text-sm"> Right click here </ContextMenuTrigger> <ContextMenuContent> <ContextMenuGroup> <ContextMenuCheckboxItem checked={showBookmarksBar} onCheckedChange={setShowBookmarksBar} > Show Bookmarks Bar </ContextMenuCheckboxItem> <ContextMenuCheckboxItem checked={showFullUrls} onCheckedChange={setShowFullUrls} > Show Full URLs </ContextMenuCheckboxItem> <ContextMenuCheckboxItem checked={showDeveloperTools} onCheckedChange={setShowDeveloperTools} > Show Developer Tools </ContextMenuCheckboxItem> </ContextMenuGroup> </ContextMenuContent> </ContextMenu> </div> )}With radio group
Right click here
import * as React from "react"import { ContextMenu, ContextMenuContent, ContextMenuGroup, ContextMenuLabel, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuTrigger } from "@/components/context-menu"export function ContextMenuWithRadio() { const [user, setUser] = React.useState("pedro") const [theme, setTheme] = React.useState("light") return ( <div className="flex flex-col gap-6"> <ContextMenu> <ContextMenuTrigger className="flex aspect-[2/0.5] w-full items-center justify-center rounded-lg border text-sm"> Right click here </ContextMenuTrigger> <ContextMenuContent> <ContextMenuGroup> <ContextMenuLabel>People</ContextMenuLabel> <ContextMenuRadioGroup value={user} onValueChange={setUser}> <ContextMenuRadioItem value="pedro"> Pedro Duarte </ContextMenuRadioItem> <ContextMenuRadioItem value="colm"> Colm Tuite </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> </div> )}With destructive items
Right click here
import { ContextMenu, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuSeparator, ContextMenuTrigger } from "@/components/context-menu"import { ArchiveIcon, PencilIcon, ShareIcon, TrashIcon } from "lucide-react"export function ContextMenuWithDestructive() { return ( <div className="flex flex-col gap-6"> <ContextMenu> <ContextMenuTrigger className="flex aspect-[2/0.5] w-full items-center justify-center rounded-lg border text-sm"> Right click here </ContextMenuTrigger> <ContextMenuContent> <ContextMenuGroup> <ContextMenuItem> <PencilIcon /> Edit </ContextMenuItem> <ContextMenuItem> <ShareIcon /> Share </ContextMenuItem> </ContextMenuGroup> <ContextMenuSeparator /> <ContextMenuGroup> <ContextMenuItem> <ArchiveIcon /> Archive </ContextMenuItem> <ContextMenuItem variant="destructive"> <TrashIcon /> Delete </ContextMenuItem> </ContextMenuGroup> </ContextMenuContent> </ContextMenu> </div> )}In dialog
import { Button } from "@/components/button"import { ContextMenu, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuSeparator, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger } from "@/components/context-menu"import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, DialogTrigger } from "@/components/dialog"import { ClipboardPasteIcon, CopyIcon, ScissorsIcon, TrashIcon } from "lucide-react"export function ContextMenuInDialog() { return ( <div className="flex flex-col gap-6"> <Dialog> <DialogTrigger asChild> <Button variant="outline">Open Dialog</Button> </DialogTrigger> <DialogContent> <DialogHeader> <DialogTitle>Context Menu Example</DialogTitle> <DialogDescription> Right click on the area below to see the context menu. </DialogDescription> </DialogHeader> <ContextMenu> <ContextMenuTrigger className="flex aspect-[2/0.5] w-full items-center justify-center rounded-lg border text-sm"> Right click here </ContextMenuTrigger> <ContextMenuContent> <ContextMenuGroup> <ContextMenuItem> <CopyIcon /> Copy </ContextMenuItem> <ContextMenuItem> <ScissorsIcon /> Cut </ContextMenuItem> <ContextMenuItem> <ClipboardPasteIcon /> Paste </ContextMenuItem> </ContextMenuGroup> <ContextMenuSeparator /> <ContextMenuSub> <ContextMenuSubTrigger>More Options</ContextMenuSubTrigger> <ContextMenuSubContent> <ContextMenuGroup> <ContextMenuItem>Save Page...</ContextMenuItem> <ContextMenuItem>Create Shortcut...</ContextMenuItem> <ContextMenuItem>Name Window...</ContextMenuItem> </ContextMenuGroup> <ContextMenuSeparator /> <ContextMenuGroup> <ContextMenuItem>Developer Tools</ContextMenuItem> </ContextMenuGroup> </ContextMenuSubContent> </ContextMenuSub> <ContextMenuSeparator /> <ContextMenuGroup> <ContextMenuItem variant="destructive"> <TrashIcon /> Delete </ContextMenuItem> </ContextMenuGroup> </ContextMenuContent> </ContextMenu> </DialogContent> </Dialog> </div> )}With inset
Right click here
import * as React from "react"import { ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger } from "@/components/context-menu"import { CopyIcon, ScissorsIcon } from "lucide-react"export function ContextMenuWithInset() { const [showBookmarks, setShowBookmarks] = React.useState(true) const [showUrls, setShowUrls] = React.useState(false) const [theme, setTheme] = React.useState("system") return ( <div className="flex flex-col gap-6"> <ContextMenu> <ContextMenuTrigger className="flex aspect-[2/0.5] w-full items-center justify-center rounded-lg border text-sm"> Right click here </ContextMenuTrigger> <ContextMenuContent className="w-44"> <ContextMenuGroup> <ContextMenuLabel>Actions</ContextMenuLabel> <ContextMenuItem> <CopyIcon /> Copy </ContextMenuItem> <ContextMenuItem> <ScissorsIcon /> Cut </ContextMenuItem> <ContextMenuItem inset>Paste</ContextMenuItem> </ContextMenuGroup> <ContextMenuSeparator /> <ContextMenuGroup> <ContextMenuLabel inset>Appearance</ContextMenuLabel> <ContextMenuCheckboxItem inset checked={showBookmarks} onCheckedChange={setShowBookmarks} > Bookmarks </ContextMenuCheckboxItem> <ContextMenuCheckboxItem inset checked={showUrls} onCheckedChange={setShowUrls} > Full URLs </ContextMenuCheckboxItem> </ContextMenuGroup> <ContextMenuSeparator /> <ContextMenuGroup> <ContextMenuLabel inset>Theme</ContextMenuLabel> <ContextMenuRadioGroup value={theme} onValueChange={setTheme}> <ContextMenuRadioItem inset value="light"> Light </ContextMenuRadioItem> <ContextMenuRadioItem inset value="dark"> Dark </ContextMenuRadioItem> <ContextMenuRadioItem inset value="system"> System </ContextMenuRadioItem> </ContextMenuRadioGroup> </ContextMenuGroup> <ContextMenuSeparator /> <ContextMenuSub> <ContextMenuSubTrigger inset>More Options</ContextMenuSubTrigger> <ContextMenuSubContent> <ContextMenuGroup> <ContextMenuItem>Save Page...</ContextMenuItem> <ContextMenuItem>Create Shortcut...</ContextMenuItem> </ContextMenuGroup> </ContextMenuSubContent> </ContextMenuSub> </ContextMenuContent> </ContextMenu> </div> )}Adapted from the shadcn/ui Context Menu (MIT).
