Skip to content

Context Menu

Stable

Actions for a specific object, opened by right-click or long-press right where the pointer is — a shortcut, never the only path.

Right-click here

Installation

$ pnpm dlx shadcn@latest add https://www.prfct.dev/r/context-menu.json

Usage

import {
  ContextMenu,
  ContextMenuContent,
  ContextMenuGroup,
  ContextMenuItem,
  ContextMenuTrigger,
} from "@/components/ui/context-menu"
<ContextMenu>
  <ContextMenuTrigger className="rounded-xl border border-dashed p-10">
    Right-click here
  </ContextMenuTrigger>
  <ContextMenuContent>
    <ContextMenuGroup>
      <ContextMenuItem>Rename</ContextMenuItem>
      <ContextMenuItem>Duplicate</ContextMenuItem>
    </ContextMenuGroup>
  </ContextMenuContent>
</ContextMenu>

ContextMenuTrigger defines the area that responds to a right-click (or a long-press on touch). The menu opens at the pointer's position. Items, groups, submenus, checkbox and radio items work exactly like Dropdown Menu's.

Examples

Browser-style menu

Everything a context menu can hold: shortcuts, a disabled item, a submenu, checkbox items and a labelled radio group.

Right-click here

Items in a list

Give every row its own ContextMenu, so the actions always apply to the object under the pointer. The trigger picks up data-popup-open while its menu is open — use it to keep the row highlighted, so people can see what the menu acts on.

Brand guidelines.pdf2.4 MB · Edited today
Q3 roadmap.fig18.1 MB · Edited yesterday
Launch checklist.md12 KB · Edited Mar 4

Canvas objects

Design tools, editors and maps rely on context menus for object-level commands. Keep the vocabulary identical to the app's main menus and show the same shortcuts.

Frame 1

Guidelines

When to use

  • To speed up actions on objects people manipulate directly: files, rows, canvas layers, messages.
  • In dense, pointer-first tools where visible action buttons would crowd the interface.

When not to use

  • As the only way to reach an action. Right-click isn't discoverable, doesn't exist on most touch devices, and is awkward from a keyboard. Every item must also be available from a visible control — a Dropdown Menu on a button, a toolbar, or the object's detail view.
  • On surfaces where people expect the browser's own menu, such as text they want to copy or links they want to open in a new tab.

Mirror the visible menus

A context menu is an accelerator for commands that already exist. Use the same labels, order and shortcuts as the row's menu or the app's menubar, so people learn the vocabulary once. Put the most frequent actions first and destructive actions last, behind a separator.

Brand guidelines.pdf
Do.The same actions are one click away on a visible button.
Brand guidelines.pdf(right-click for options)
Don’t.Actions that only exist behind a right-click are invisible to most people.

Keep it short

Context menus are read at the pointer, under time pressure. Aim for fewer than ten items in two or three groups, avoid more than one level of submenus, and never put long-form content inside.

Accessibility

Context Menu is built on the Base UI Context Menu, which follows the WAI-ARIA menu pattern once open (the APG describes menus and menubars on one page).

KeyBehavior
ShiftF10
With focus inside the trigger area, opens the menu — the platform's keyboard equivalent of a right-click. Also the ContextMenu key on Windows keyboards.
Moves focus between items; loops at the ends.
HomeEnd
Focuses the first or last item.
Opens or closes a submenu.
EnterSpace
Activates the focused item.
A–Z
Typeahead to the next item starting with the typed characters.
Esc
Closes the menu.
  • Touch. A long-press on the trigger opens the menu, so the same actions work on phones and tablets.
  • Parity. Because context menus are hard to discover with assistive technology, the visible alternative isn't optional — it's what makes the actions accessible at all.

API reference

ContextMenu

The root. Accepts the Base UI ContextMenu.Root props.

PropTypeDefault
open

Controlled open state.

booleanNo default
defaultOpen

Initial open state when uncontrolled.

booleanfalse
onOpenChange

Called when the menu opens or closes.

(open: boolean, details) => voidNo default
loopFocus

Whether arrow-key focus wraps around.

booleantrue
disabled

Disables the menu; the browser's own menu shows instead.

booleanfalse

ContextMenuTrigger

The area that listens for right-click and long-press. Renders a <div> with select-none; style it like any container. It receives data-popup-open while its menu is open.

ContextMenuContent

PropTypeDefault
side

Preferred side relative to the pointer.

"top" | "bottom" | "left" | "right" | "inline-start" | "inline-end""right"
align

Alignment against the pointer position.

"start" | "center" | "end""start"
sideOffset

Gap from the pointer, in px.

number0
alignOffset

Shift along the alignment axis, in px.

number4

ContextMenuItem

PropTypeDefault
variant

Destructive items use the danger color.

"default" | "destructive""default"
inset

Adds leading space to align with items that have icons.

booleanfalse
onClick

Called when the item is activated.

(event) => voidNo default
closeOnClick

Whether activating the item closes the menu.

booleantrue
disabled

Skips the item and ignores clicks.

booleanfalse
label

Text used for typeahead when the content isn't plain text.

stringNo default

Other parts

ContextMenuCheckboxItem, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSub, ContextMenuSubTrigger, ContextMenuSubContent, ContextMenuLabel, ContextMenuSeparator, ContextMenuShortcut and ContextMenuGroup share their API with the equivalent Dropdown Menu parts.