Skip to Content
⭐️ Leave a star →
ComponentsContextMenu

Context Menu

Right-click triggered menu. Positioned at the cursor; closes on outside click, scroll, or Escape. Content is portaled to document.body so it escapes any transformed/clipped ancestor.

Features

Opens at the exact cursor position on right-click.
Portaled to body so it escapes transformed ancestors.
Closes on outside click, Escape, or scroll outside the menu.
Disabled items and separators.
Blocks page scroll while open (no layout shift).

Example

Right-click here
import { ContextMenu } from '@wire-ui/react' <ContextMenu.Root> <ContextMenu.Trigger>Right-click here</ContextMenu.Trigger> <ContextMenu.Content> <ContextMenu.Item onSelect={() => console.log('cut')}>Cut</ContextMenu.Item> <ContextMenu.Item onSelect={() => console.log('copy')}>Copy</ContextMenu.Item> <ContextMenu.Separator /> <ContextMenu.Item disabled>Paste</ContextMenu.Item> </ContextMenu.Content> </ContextMenu.Root>

Styling

Root and Trigger expose data-state ("open" / "closed"). Item exposes the full set of interactive data attributes plus data-disabled.

<ContextMenu.Item className=" data-[hover]:bg-[#f5f5f5] data-[focus-visible]:bg-[#f5f5f5] data-[disabled]:opacity-40 data-[disabled]:cursor-not-allowed "> Item </ContextMenu.Item>

Using data attributes

[data-state="open"] { /* trigger highlight while menu is open */ } [data-disabled] { opacity: 0.4; cursor: not-allowed; } [data-hover] { background: #f5f5f5; } [data-focus-visible] { background: #f5f5f5; }

Root props

PropTypeDefaultDescription
openbooleanControlled open state
defaultOpenbooleanfalseInitial open state
onOpenChange(open: boolean) => voidCalled when open state changes
disabledbooleanfalseDisables the trigger (no right-click handling)

Item props

PropTypeDefaultDescription
disabledbooleanfalseDisables this item
onSelect() => voidCalled when the item is selected (also closes the menu)

Data attributes

AttributeElementValues
data-stateRoot, Trigger, Content"open" / "closed"
data-disabledItemPresent when disabled
data-hover / data-active / data-focus-visibleItemStandard interactive states

Content sets role="menu". Items set role="menuitem" with aria-disabled when disabled. Separator sets role="separator".

Accessibility

  • The contextmenu event is intercepted on the Trigger; the native browser menu is suppressed.
  • Content is portaled to document.body and uses position: fixed, so transformed ancestors don’t affect placement.
  • Items are keyboard-activatable with Enter or Space.
  • Page scroll (wheel, touch, arrow keys) is blocked while the menu is open — no layout shift since the scrollbar stays in place.

Keyboard Interactions

KeyDescription
EnterActivates the focused item.
SpaceActivates the focused item.
TabMoves focus to the next item.
EscapeCloses the menu.

Internals

Since 0.3.0, the outside-click and Escape handling is delegated to useEventListener — null-target safe and no manual addEventListener / cleanup boilerplate. No public API change.
Last updated on

MIT License © 2026 wire-ui

Context Menu – Wire UI