"use client";
import { ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger,} from "@/components/ui/context-menu";
export function ContextMenuDemo() { return ( <ContextMenu> <ContextMenuTrigger className="flex aspect-video w-full max-w-xs items-center justify-center rounded-xl border border-dashed text-sm"> <span className="pointer-fine:inline-block hidden"> Right click here </span> <span className="pointer-coarse:inline-block hidden"> Long press here </span> </ContextMenuTrigger> <ContextMenuContent className="w-48"> <ContextMenuGroup> <ContextMenuItem> Back <ContextMenuShortcut>⌘[</ContextMenuShortcut> </ContextMenuItem> <ContextMenuItem disabled> Forward <ContextMenuShortcut>⌘]</ContextMenuShortcut> </ContextMenuItem> <ContextMenuItem> Reload <ContextMenuShortcut>⌘R</ContextMenuShortcut> </ContextMenuItem> <ContextMenuSub> <ContextMenuSubTrigger>More Tools</ContextMenuSubTrigger> <ContextMenuSubContent className="w-44"> <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> </ContextMenuGroup> <ContextMenuSeparator /> <ContextMenuGroup> <ContextMenuCheckboxItem checked> Show Bookmarks </ContextMenuCheckboxItem> <ContextMenuCheckboxItem>Show Full URLs</ContextMenuCheckboxItem> </ContextMenuGroup> <ContextMenuSeparator /> <ContextMenuGroup> <ContextMenuRadioGroup value="pedro"> <ContextMenuLabel>People</ContextMenuLabel> <ContextMenuRadioItem value="pedro"> Pedro Duarte </ContextMenuRadioItem> <ContextMenuRadioItem value="colm">Colm Tuite</ContextMenuRadioItem> </ContextMenuRadioGroup> </ContextMenuGroup> </ContextMenuContent> </ContextMenu> );}pnpm dlx shadcn@latest add @herocn/context-menuimport { ContextMenu, ContextMenuContent, ContextMenuItem, ContextMenuTrigger,} from "@/components/ui/context-menu"<ContextMenu> <ContextMenuTrigger>Right click here</ContextMenuTrigger> <ContextMenuContent> <ContextMenuItem>Profile</ContextMenuItem> <ContextMenuItem>Billing</ContextMenuItem> <ContextMenuItem>Team</ContextMenuItem> <ContextMenuItem>Subscription</ContextMenuItem> </ContextMenuContent></ContextMenu>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 └── ContextMenuItemA simple context menu with a few actions.
"use client";
import { ContextMenu, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuTrigger,} from "@/components/ui/context-menu";
export function ContextMenuBasic() { return ( <ContextMenu> <ContextMenuTrigger className="flex aspect-video w-full max-w-xs items-center justify-center rounded-xl border border-dashed text-sm"> <span className="pointer-fine:inline-block hidden"> Right click here </span> <span className="pointer-coarse:inline-block hidden"> Long press here </span> </ContextMenuTrigger> <ContextMenuContent> <ContextMenuGroup> <ContextMenuItem>Back</ContextMenuItem> <ContextMenuItem disabled>Forward</ContextMenuItem> <ContextMenuItem>Reload</ContextMenuItem> </ContextMenuGroup> </ContextMenuContent> </ContextMenu> );}Use ContextMenuSub to nest secondary actions.
"use client";
import { ContextMenu, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger,} from "@/components/ui/context-menu";
export function ContextMenuSubmenu() { return ( <ContextMenu> <ContextMenuTrigger className="flex aspect-video w-full max-w-xs items-center justify-center rounded-xl border border-dashed text-sm"> <span className="pointer-fine:inline-block hidden"> Right click here </span> <span className="pointer-coarse:inline-block hidden"> Long press here </span> </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> );}Add ContextMenuShortcut to show keyboard hints.
"use client";
import { ContextMenu, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuTrigger,} from "@/components/ui/context-menu";
export function ContextMenuShortcuts() { return ( <ContextMenu> <ContextMenuTrigger className="flex aspect-video w-full max-w-xs items-center justify-center rounded-xl border border-dashed text-sm"> <span className="pointer-fine:inline-block hidden"> Right click here </span> <span className="pointer-coarse:inline-block hidden"> Long press here </span> </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> );}Group related actions and separate them with dividers.
"use client";
import { ContextMenu, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuSeparator, ContextMenuShortcut, ContextMenuTrigger,} from "@/components/ui/context-menu";
export function ContextMenuGroups() { return ( <ContextMenu> <ContextMenuTrigger className="flex aspect-video w-full max-w-xs items-center justify-center rounded-xl border border-dashed text-sm"> <span className="pointer-fine:inline-block hidden"> Right click here </span> <span className="pointer-coarse:inline-block hidden"> Long press here </span> </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> </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> );}Combine icons with labels for quick scanning.
"use client";
import { ClipboardPasteIcon, CopyIcon, ScissorsIcon, TrashIcon,} from "lucide-react";import { ContextMenu, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuSeparator, ContextMenuTrigger,} from "@/components/ui/context-menu";
export function ContextMenuIcons() { return ( <ContextMenu> <ContextMenuTrigger className="flex aspect-video w-full max-w-xs items-center justify-center rounded-xl border border-dashed text-sm"> <span className="pointer-fine:inline-block hidden"> Right click here </span> <span className="pointer-coarse:inline-block hidden"> Long press here </span> </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> );}Use ContextMenuCheckboxItem for toggles.
"use client";
import { ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuTrigger,} from "@/components/ui/context-menu";
export function ContextMenuCheckboxes() { return ( <ContextMenu> <ContextMenuTrigger className="flex aspect-video w-full max-w-xs items-center justify-center rounded-xl border border-dashed text-sm"> <span className="pointer-fine:inline-block hidden"> Right click here </span> <span className="pointer-coarse:inline-block hidden"> Long press here </span> </ContextMenuTrigger> <ContextMenuContent> <ContextMenuGroup> <ContextMenuCheckboxItem defaultChecked> Show Bookmarks Bar </ContextMenuCheckboxItem> <ContextMenuCheckboxItem>Show Full URLs</ContextMenuCheckboxItem> <ContextMenuCheckboxItem defaultChecked> Show Developer Tools </ContextMenuCheckboxItem> </ContextMenuGroup> </ContextMenuContent> </ContextMenu> );}Use ContextMenuRadioItem for exclusive choices.
"use client";
import * as React from "react";import { ContextMenu, ContextMenuContent, ContextMenuGroup, ContextMenuLabel, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuTrigger,} from "@/components/ui/context-menu";
export function ContextMenuRadio() { const [user, setUser] = React.useState("pedro"); const [theme, setTheme] = React.useState("light");
return ( <ContextMenu> <ContextMenuTrigger className="flex aspect-video w-full max-w-xs items-center justify-center rounded-xl border border-dashed text-sm"> <span className="pointer-fine:inline-block hidden"> Right click here </span> <span className="pointer-coarse:inline-block hidden"> Long press here </span> </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> );}Use variant="destructive" to style the menu item as destructive.
"use client";
import { PencilIcon, ShareIcon, TrashIcon } from "lucide-react";import { ContextMenu, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuSeparator, ContextMenuTrigger,} from "@/components/ui/context-menu";
export function ContextMenuDestructive() { return ( <ContextMenu> <ContextMenuTrigger className="flex aspect-video w-full max-w-xs items-center justify-center rounded-xl border border-dashed text-sm"> <span className="pointer-fine:inline-block hidden"> Right click here </span> <span className="pointer-coarse:inline-block hidden"> Long press here </span> </ContextMenuTrigger> <ContextMenuContent> <ContextMenuGroup> <ContextMenuItem> <PencilIcon /> Edit </ContextMenuItem> <ContextMenuItem> <ShareIcon /> Share </ContextMenuItem> </ContextMenuGroup> <ContextMenuSeparator /> <ContextMenuGroup> <ContextMenuItem variant="destructive"> <TrashIcon /> Delete </ContextMenuItem> </ContextMenuGroup> </ContextMenuContent> </ContextMenu> );}Control submenu placement with side and align props.
"use client";
import { ContextMenu, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuTrigger,} from "@/components/ui/context-menu";
export function ContextMenuSides() { return ( <div className="grid w-full max-w-sm grid-cols-2 gap-4"> <ContextMenu> <ContextMenuTrigger className="flex aspect-video w-full max-w-xs items-center justify-center rounded-xl border border-dashed text-sm"> <span className="pointer-fine:inline-block hidden"> Right click (top) </span> <span className="pointer-coarse:inline-block hidden"> Long press (top) </span> </ContextMenuTrigger> <ContextMenuContent side="top"> <ContextMenuGroup> <ContextMenuItem>Back</ContextMenuItem> <ContextMenuItem>Forward</ContextMenuItem> <ContextMenuItem>Reload</ContextMenuItem> </ContextMenuGroup> </ContextMenuContent> </ContextMenu> <ContextMenu> <ContextMenuTrigger className="flex aspect-video w-full max-w-xs items-center justify-center rounded-xl border border-dashed text-sm"> <span className="pointer-fine:inline-block hidden"> Right click (right) </span> <span className="pointer-coarse:inline-block hidden"> Long press (right) </span> </ContextMenuTrigger> <ContextMenuContent side="right"> <ContextMenuGroup> <ContextMenuItem>Back</ContextMenuItem> <ContextMenuItem>Forward</ContextMenuItem> <ContextMenuItem>Reload</ContextMenuItem> </ContextMenuGroup> </ContextMenuContent> </ContextMenu> <ContextMenu> <ContextMenuTrigger className="flex aspect-video w-full max-w-xs items-center justify-center rounded-xl border border-dashed text-sm"> <span className="pointer-fine:inline-block hidden"> Right click (bottom) </span> <span className="pointer-coarse:inline-block hidden"> Long press (bottom) </span> </ContextMenuTrigger> <ContextMenuContent side="bottom"> <ContextMenuGroup> <ContextMenuItem>Back</ContextMenuItem> <ContextMenuItem>Forward</ContextMenuItem> <ContextMenuItem>Reload</ContextMenuItem> </ContextMenuGroup> </ContextMenuContent> </ContextMenu> <ContextMenu> <ContextMenuTrigger className="flex aspect-video w-full max-w-xs items-center justify-center rounded-xl border border-dashed text-sm"> <span className="pointer-fine:inline-block hidden"> Right click (left) </span> <span className="pointer-coarse:inline-block hidden"> Long press (left) </span> </ContextMenuTrigger> <ContextMenuContent side="left"> <ContextMenuGroup> <ContextMenuItem>Back</ContextMenuItem> <ContextMenuItem>Forward</ContextMenuItem> <ContextMenuItem>Reload</ContextMenuItem> </ContextMenuGroup> </ContextMenuContent> </ContextMenu> </div> );}"use client";
import { ArrowLeftIcon, ArrowRightIcon, RotateCwIcon } from "lucide-react";import * as React from "react";
import { type Translations, useTranslation,} from "@/components/language-selector";import { ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger,} from "@/components/ui/context-menu";
const translations: Translations = { en: { dir: "ltr", values: { rightClick: "Right click here", longPress: "Long press here", navigation: "Navigation", back: "Back", forward: "Forward", reload: "Reload", moreTools: "More Tools", savePage: "Save Page...", createShortcut: "Create Shortcut...", nameWindow: "Name Window...", developerTools: "Developer Tools", delete: "Delete", showBookmarks: "Show Bookmarks", showFullUrls: "Show Full URLs", people: "People", pedro: "Pedro Duarte", colm: "Colm Tuite", }, }, ar: { dir: "rtl", values: { rightClick: "انقر بزر الماوس الأيمن هنا", longPress: "اضغط مطولاً هنا", navigation: "التنقل", back: "رجوع", forward: "تقدم", reload: "إعادة تحميل", moreTools: "المزيد من الأدوات", savePage: "حفظ الصفحة...", createShortcut: "إنشاء اختصار...", nameWindow: "تسمية النافذة...", developerTools: "أدوات المطور", delete: "حذف", showBookmarks: "إظهار الإشارات المرجعية", showFullUrls: "إظهار عناوين URL الكاملة", people: "الأشخاص", pedro: "بيدرو دوارتي", colm: "كولم تويت", }, }, he: { dir: "rtl", values: { rightClick: "לחץ לחיצה ימנית כאן", longPress: "לחץ לחיצה ארוכה כאן", navigation: "ניווט", back: "חזור", forward: "קדימה", reload: "רענן", moreTools: "כלים נוספים", savePage: "שמור עמוד...", createShortcut: "צור קיצור דרך...", nameWindow: "שם חלון...", developerTools: "כלי מפתח", delete: "מחק", showBookmarks: "הצג סימניות", showFullUrls: "הצג כתובות URL מלאות", people: "אנשים", pedro: "פדרו דוארטה", colm: "קולם טויט", }, },};
export function ContextMenuRtl() { const { dir, language, t } = useTranslation(translations, "ar"); const [people, setPeople] = React.useState("pedro");
return ( <ContextMenu> <ContextMenuTrigger className="flex aspect-video w-full max-w-xs items-center justify-center rounded-xl border border-dashed text-sm"> <span className="pointer-fine:inline-block hidden">{t.rightClick}</span> <span className="pointer-coarse:inline-block hidden"> {t.longPress} </span> </ContextMenuTrigger> <ContextMenuContent className="w-48" dir={dir} data-lang={dir === "rtl" ? language : undefined} > <ContextMenuGroup> <ContextMenuSub> <ContextMenuSubTrigger>{t.navigation}</ContextMenuSubTrigger> <ContextMenuSubContent className="w-44" dir={dir} data-lang={dir === "rtl" ? language : undefined} > <ContextMenuGroup> <ContextMenuItem> <ArrowLeftIcon className="rtl:rotate-180" data-icon="inline-end" /> {t.back} <ContextMenuShortcut>⌘[</ContextMenuShortcut> </ContextMenuItem> <ContextMenuItem disabled> <ArrowRightIcon className="rtl:rotate-180" data-icon="inline-end" /> {t.forward} <ContextMenuShortcut>⌘]</ContextMenuShortcut> </ContextMenuItem> <ContextMenuItem> <RotateCwIcon /> {t.reload} <ContextMenuShortcut>⌘R</ContextMenuShortcut> </ContextMenuItem> </ContextMenuGroup> </ContextMenuSubContent> </ContextMenuSub> <ContextMenuSub> <ContextMenuSubTrigger>{t.moreTools}</ContextMenuSubTrigger> <ContextMenuSubContent className="w-44" dir={dir} data-lang={dir === "rtl" ? language : undefined} > <ContextMenuGroup> <ContextMenuItem>{t.savePage}</ContextMenuItem> <ContextMenuItem>{t.createShortcut}</ContextMenuItem> <ContextMenuItem>{t.nameWindow}</ContextMenuItem> </ContextMenuGroup> <ContextMenuSeparator /> <ContextMenuGroup> <ContextMenuItem>{t.developerTools}</ContextMenuItem> </ContextMenuGroup> <ContextMenuSeparator /> <ContextMenuGroup> <ContextMenuItem variant="destructive"> {t.delete} </ContextMenuItem> </ContextMenuGroup> </ContextMenuSubContent> </ContextMenuSub> </ContextMenuGroup> <ContextMenuSeparator /> <ContextMenuGroup> <ContextMenuCheckboxItem checked> {t.showBookmarks} </ContextMenuCheckboxItem> <ContextMenuCheckboxItem>{t.showFullUrls}</ContextMenuCheckboxItem> </ContextMenuGroup> <ContextMenuSeparator /> <ContextMenuGroup> <ContextMenuRadioGroup value={people} onValueChange={setPeople}> <ContextMenuLabel>{t.people}</ContextMenuLabel> <ContextMenuRadioItem value="pedro">{t.pedro}</ContextMenuRadioItem> <ContextMenuRadioItem value="colm">{t.colm}</ContextMenuRadioItem> </ContextMenuRadioGroup> </ContextMenuGroup> </ContextMenuContent> </ContextMenu> );}See the Base UI documentation for the full API reference.