Context menustandard
마우스 오른쪽 클릭(또는 길게 누르기)으로 여는 맥락 메뉴(context menu)입니다. shadcn base-nova 의 `context-menu` 를 그대로 싣습니다. 눌러서 여는 메뉴는 `dropdown-menu` 를 씁니다.
설치
pnpm
pnpm dlx shadcn@4.23.0 add @uikit/context-menuDefault
context-menu-example.tsx
"use client"
import * as React from "react"
import { Example, ExampleWrapper,} from "@/components/example"import { Button } from "@/components/ui/button"import { ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger,} from "@/components/ui/context-menu"import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, DialogTrigger,} from "@/components/ui/dialog"import { ArchiveIcon, ClipboardPasteIcon, CopyIcon, PencilIcon, ScissorsIcon, ShareIcon, TrashIcon } from "lucide-react"
export default function ContextMenuExample() { return ( <ExampleWrapper> <ContextMenuBasic /> <ContextMenuWithIcons /> <ContextMenuWithSides /> <ContextMenuWithShortcuts /> <ContextMenuWithSubmenu /> <ContextMenuWithGroups /> <ContextMenuWithCheckboxes /> <ContextMenuWithRadio /> <ContextMenuWithDestructive /> <ContextMenuInDialog /> <ContextMenuWithInset /> </ExampleWrapper> )}
function ContextMenuBasic() { return ( <Example title="Basic"> <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> </Example> )}
function ContextMenuWithIcons() { return ( <Example title="With Icons"> <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> </Example> )}
function ContextMenuWithShortcuts() { return ( <Example title="With Shortcuts"> <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> </Example> )}
function ContextMenuWithSubmenu() { return ( <Example title="With Submenu"> <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> </Example> )}
function ContextMenuWithGroups() { return ( <Example title="With Groups, Labels & Separators"> <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> </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> </Example> )}
function ContextMenuWithCheckboxes() { return ( <Example title="With Checkboxes"> <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 defaultChecked> Show Bookmarks Bar </ContextMenuCheckboxItem> <ContextMenuCheckboxItem>Show Full URLs</ContextMenuCheckboxItem> <ContextMenuCheckboxItem defaultChecked> Show Developer Tools </ContextMenuCheckboxItem> </ContextMenuGroup> </ContextMenuContent> </ContextMenu> </Example> )}
function ContextMenuWithRadio() { const [user, setUser] = React.useState("pedro") const [theme, setTheme] = React.useState("light")
return ( <Example title="With Radio Group"> <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> </Example> )}
function ContextMenuWithDestructive() { return ( <Example title="With Destructive Items"> <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> </Example> )}
function ContextMenuWithSides() { return ( <Example title="With Sides" containerClassName="col-span-2"> <div className="flex flex-wrap justify-center gap-2"> {( [ "inline-start", "left", "top", "bottom", "right", "inline-end", ] as const ).map((side) => ( <ContextMenu key={side}> <ContextMenuTrigger className="flex aspect-[2/0.5] items-center justify-center rounded-lg border p-4 text-sm capitalize"> {side.replace("-", " ")} </ContextMenuTrigger> <ContextMenuContent side={side}> <ContextMenuGroup> <ContextMenuItem>Back</ContextMenuItem> <ContextMenuItem>Forward</ContextMenuItem> <ContextMenuItem>Reload</ContextMenuItem> </ContextMenuGroup> </ContextMenuContent> </ContextMenu> ))} </div> </Example> )}
function ContextMenuInDialog() { return ( <Example title="In Dialog"> <Dialog> <DialogTrigger render={<Button variant="outline" />}> Open Dialog </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> </Example> )}
function ContextMenuWithInset() { const [showBookmarks, setShowBookmarks] = React.useState(true) const [showUrls, setShowUrls] = React.useState(false) const [theme, setTheme] = React.useState("system")
return ( <Example title="With Inset"> <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> </Example> )}