Join our Discord Community

Context Menu

React context menu with right-click actions, submenus, and keyboard navigation. Perfect for file managers, editors, and interactive interfaces.

Need right-click menus that feel native? Context menus appear exactly where users expect them - at their cursor position. Perfect for file operations, text editing, and any interface where users need quick actions without cluttering the main UI.

Loading component...

Built with modern React patterns and full accessibility support.

npx shadcn@latest add context-menu

Why context menus work so well

Using the same patterns users know from their operating system:

  • Right-click anywhere - Works exactly like desktop apps
  • Cursor positioning - Menu appears right where you clicked
  • Keyboard shortcuts - Arrow keys navigate, Enter selects, Escape closes
  • Nested submenus - Handle complex action hierarchies naturally
  • Screen reader friendly - Announces menu items and structure
  • Mobile support - Long press works on touch devices
  • Fast and lightweight - No performance impact when closed

Context menu patterns that users expect

File and folder operations

The classic right-click menu for managing items:

Loading component...

Actions with visual icons

Icons help users quickly identify common actions:

Loading component...

Toggle settings and preferences

Perfect for view options and application settings:

Loading component...

Choose between options

Radio groups let users pick one choice from several:

Loading component...

Organize complex actions

Submenus keep related actions grouped without clutter:

Loading component...

Handle restricted content

Show what's available and what isn't with disabled states:

Loading component...

API Reference

ContextMenu

Contains all the parts of a context menu. The root component.

PropTypeDefaultDescription
dir"ltr" | "rtl"-The reading direction of the menu when applicable
onOpenChange(open: boolean) => void-Event handler called when the open state changes
modalbooleantrueWhether the menu is modal (traps focus and blocks interaction)

ContextMenuTrigger

The area that opens the context menu. Wrap it around the target you want the context menu to open from.

PropTypeDefaultDescription
asChildbooleanfalseChange the default rendered element for the one passed as a child
disabledbooleanfalseWhen true, the context menu won't open

ContextMenuPortal

When used, portals the content part into the body.

PropTypeDefaultDescription
forceMountbooleanfalseUsed to force mounting when more control is needed
containerHTMLElementdocument.bodySpecify a container element to portal the content into

ContextMenuContent

The component that pops out when the context menu is open.

PropTypeDefaultDescription
asChildbooleanfalseChange the default rendered element for the one passed as a child
loopbooleanfalseWhether keyboard navigation should loop around
onCloseAutoFocus(event: Event) => void-Event handler called when focus moves to the trigger after closing
onEscapeKeyDown(event: KeyboardEvent) => void-Event handler called when the escape key is down
onPointerDownOutside(event: PointerDownOutsideEvent) => void-Event handler called when a pointer event occurs outside
onFocusOutside(event: FocusOutsideEvent) => void-Event handler called when focus moves outside
onInteractOutside(event: InteractOutsideEvent) => void-Event handler called when an interaction happens outside
forceMountbooleanfalseUsed to force mounting when more control is needed
alignOffsetnumber0The distance in pixels from the anchor
avoidCollisionsbooleantrueWhether to avoid collisions with the boundary edges
collisionBoundaryElement | null | Array<Element | null>[]The element used as the collision boundary
collisionPaddingnumber | Partial<Record<Side, number>>0The distance in pixels from the boundary edges
sticky"partial" | "always""partial"The sticky behavior on the align axis
hideWhenDetachedbooleanfalseWhether to hide when the reference element becomes fully occluded

ContextMenuItem

The component that contains the context menu items.

PropTypeDefaultDescription
asChildbooleanfalseChange the default rendered element for the one passed as a child
disabledbooleanfalseWhen true, prevents the user from interacting with the item
onSelect(event: Event) => void-Event handler called when the user selects an item
textValuestring-Optional text used for typeahead purposes

ContextMenuGroup

Used to group multiple ContextMenuItems.

PropTypeDefaultDescription
asChildbooleanfalseChange the default rendered element for the one passed as a child

ContextMenuLabel

Used to render a label. It won't be focusable using arrow keys.

PropTypeDefaultDescription
asChildbooleanfalseChange the default rendered element for the one passed as a child

ContextMenuCheckboxItem

An item that can be controlled and rendered like a checkbox.

PropTypeDefaultDescription
asChildbooleanfalseChange the default rendered element for the one passed as a child
checkedboolean | "indeterminate"-The controlled checked state of the item
onCheckedChange(checked: boolean) => void-Event handler called when the checked state changes
disabledbooleanfalseWhen true, prevents the user from interacting with the item
onSelect(event: Event) => void-Event handler called when the user selects an item
textValuestring-Optional text used for typeahead purposes

ContextMenuRadioGroup

Used to group multiple ContextMenuRadioItems.

PropTypeDefaultDescription
asChildbooleanfalseChange the default rendered element for the one passed as a child
valuestring-The controlled value of the radio item to check
onValueChange(value: string) => void-Event handler called when the value changes

ContextMenuRadioItem

An item that can be controlled and rendered like a radio.

PropTypeDefaultDescription
asChildbooleanfalseChange the default rendered element for the one passed as a child
valuestring-The unique value of the item
disabledbooleanfalseWhen true, prevents the user from interacting with the item
onSelect(event: Event) => void-Event handler called when the user selects an item
textValuestring-Optional text used for typeahead purposes

ContextMenuItemIndicator

Renders when the parent ContextMenuCheckboxItem or ContextMenuRadioItem is checked.

PropTypeDefaultDescription
asChildbooleanfalseChange the default rendered element for the one passed as a child
forceMountbooleanfalseUsed to force mounting when more control is needed

ContextMenuSeparator

Used to visually separate items in the context menu.

PropTypeDefaultDescription
asChildbooleanfalseChange the default rendered element for the one passed as a child

ContextMenuSub

Contains all the parts of a submenu.

PropTypeDefaultDescription
defaultOpenbooleanfalseThe open state of the submenu when initially rendered
openboolean-The controlled open state of the submenu
onOpenChange(open: boolean) => void-Event handler called when the open state changes

ContextMenuSubTrigger

An item that opens a submenu. Must be rendered inside ContextMenuSub.

PropTypeDefaultDescription
asChildbooleanfalseChange the default rendered element for the one passed as a child
disabledbooleanfalseWhen true, prevents the user from interacting with the item
textValuestring-Optional text used for typeahead purposes

ContextMenuSubContent

The component that pops out when a submenu is open. Must be rendered inside ContextMenuSub.

PropTypeDefaultDescription
asChildbooleanfalseChange the default rendered element for the one passed as a child
loopbooleanfalseWhether keyboard navigation should loop around
onEscapeKeyDown(event: KeyboardEvent) => void-Event handler called when the escape key is down
onPointerDownOutside(event: PointerDownOutsideEvent) => void-Event handler called when a pointer event occurs outside
onFocusOutside(event: FocusOutsideEvent) => void-Event handler called when focus moves outside
onInteractOutside(event: InteractOutsideEvent) => void-Event handler called when an interaction happens outside
forceMountbooleanfalseUsed to force mounting when more control is needed
sideOffsetnumber0The distance in pixels from the trigger
alignOffsetnumber0The distance in pixels from the anchor
avoidCollisionsbooleantrueWhether to avoid collisions with the boundary edges
collisionBoundaryElement | null | Array<Element | null>[]The element used as the collision boundary
collisionPaddingnumber | Partial<Record<Side, number>>0The distance in pixels from the boundary edges
arrowPaddingnumber0The padding between the arrow and the edges of the content
sticky"partial" | "always""partial"The sticky behavior on the align axis
hideWhenDetachedbooleanfalseWhether to hide when the reference element becomes fully occluded

ContextMenuShortcut

Used to display keyboard shortcuts. This is a custom component, not from Radix UI.

PropTypeDefaultDescription
classNamestring-Additional CSS classes
childrenReact.ReactNode-The shortcut content to display

Keyboard Navigation

KeyDescription
SpaceActivates the focused item
EnterActivates the focused item
ArrowDownMoves focus to the next item
ArrowUpMoves focus to the previous item
ArrowRightWhen focus is on ContextMenuSubTrigger, opens the submenu
ArrowLeftWhen focus is on ContextMenuSubTrigger, closes the submenu
EscapeCloses the context menu and moves focus to the ContextMenuTrigger

Context menu best practices

What makes context menus feel natural and useful:

  • Use action verbs - "Edit" and "Delete" instead of "Edit this item" or "Delete selected"
  • Group related actions - Use separators between different types of operations
  • Put common actions first - Most-used items at the top save clicks
  • Mark dangerous actions - Use red/destructive styling for things like "Delete"
  • Show keyboard shortcuts - Power users appreciate seeing ⌘K next to actions
  • Disable unavailable actions - Gray out options that don't apply right now
  • Keep menus shallow - Deep nesting gets confusing fast
  • Test on mobile - Long-press should work just like right-click