Context menu
Secondary actions kept close to the selected object.
pnpm dlx shadcn@latest add @uiarc/context-menuLive · keyboard ready
- Secondary actions on a file, card, or row where a visible menu button would add clutter.
- Desktop-style right-click menus that also open from the keyboard with Shift+F10 or the ContextMenu key.
- Short flat lists of item actions with one destructive option.
- Use dropdown-menu when the actions deserve a visible trigger.
- Use swipe-actions for touch-first lists like an inbox.
- Avoid it on targets that need their own click action, since a plain click on the target also opens the menu.
Installation
Add Context menu with the shadcn CLI, or copy the source by hand.
pnpm dlx shadcn@latest add @uiarc/context-menuAdds the component and its local dependencies, and installs motion, lucide-react. First time? Add the @uiarc registry to components.json, or use the full URL:
example.tsx
import { ContextMenu } from "@/registry/components/context-menu/context-menu";import { Copy, Trash2 } from "lucide-react"; export function FileTile({ file }: { file: File }) { return ( <ContextMenu label={`Actions for ${file.name}`} items={[ { id: "copy", label: "Copy link", icon: <Copy size={15} />, onSelect: () => copyLink(file) }, { id: "delete", label: "Delete file", icon: <Trash2 size={15} />, destructive: true, onSelect: () => remove(file) }, ]} > <FilePreview file={file} /> </ContextMenu> );}ContextMenu
Wraps content and opens a menu at the pointer on right-click, or under the target on click and keyboard.
PropTypeDefaultDescription
childrenRequiredReactNode–The target area.itemsRequiredContextMenuItem[]–Items: { id, label, icon?, onSelect?, disabled?, destructive?, checked? }.labelstring"Context menu"Accessible name for both the target and the menu.- ContextMenuorShift+F10
- Opens the menu under the focused target.
- ArrowDownorArrowUp
- Moves between enabled items, wrapping at the ends.
- HomeorEnd
- Jumps to the first or last enabled item.
- EnterorSpace
- Selects the focused item and closes the menu.
- Escape
- Closes the menu and returns focus to the target.
- The target is focusable with aria-haspopup="menu" and aria-expanded; the menu has role="menu" and items role="menuitem".
- Opening focuses the first enabled item; closing returns focus to the target.
- Items without an icon show a check when checked, but checked state is not exposed to assistive tech, so say it in the label if it matters.
- The menu grows from the pointer on a snappy spring, even when clamped away from a viewport edge; reopening fades the old one out in place.
- A shared highlight glides between rows for the pointer and jumps for the keyboard.
- Reduced motion drops the scale and glide and uses a short opacity fade.
- The menu is clamped 8px inside the viewport and capped at the viewport width minus 16px, with a max height of 300px and scrolling beyond that.
- On touch, a tap on the target opens the menu under it, so it works without a right mouse button.
- The menu closes on any scroll or resize instead of repositioning.
- The menu mounts only while open and is positioned once from the pointer, with no scroll tracking loop.
- Items are plain buttons with one shared highlight element; there is no virtualization, so keep the list short.
Notes for AI
Give your coding assistant the Markdown reference instead of screenshots.
- Use for secondary actions on a content object (file, card, row) where a visible menu button would add clutter. Use dropdown-menu when the commands deserve a visible trigger.
- A plain click on the target also opens the menu, so do not wrap targets that need their own click action.
- The menu closes on scroll, resize, and outside press; keep items to a short flat list.
The full library index for assistants is at /llms.txt.