Context Menu

Right-click action menu.

Usage

Trigger is the right-click region, not a button — it wraps the content the menu acts on. Content portals to <body> and Bits positions it at the pointer, owning role="menu", roving focus and keyboard navigation.

Right-click this row

Never the only route

Right-click is undiscoverable, and touch devices have no right-click at all. Every action offered here must also be reachable from a visible control.

That is not a nitpick — put "Delete" only in a context menu and a phone user simply cannot delete anything. Treat this as an accelerator for people who already know the action exists: pair it with a Dropdown Menu on a visible trigger, or with inline buttons on the row.

Shared with Dropdown Menu

Item, Group, Label and Separator are the same components Dropdown Menu uses. Bits re-exports identical menu internals under both namespaces, so one styled implementation serves each rather than two copies of the same CSS drifting apart.

They stay context-aware: Bits derives its data attributes from whichever Root wraps them, so the same wrapper emits data-context-menu-item here and data-dropdown-menu-item there. The class is sve-menu-item in both, which is what keeps the two menus looking identical.

Props

ContextMenu.Root

PropTypeDefault
children bits-ui Snippet<[]> | undefined
dir bits-ui The direction of the site.Direction | undefined"ltr"
onOpenChange bits-ui A callback that is called when the menu is opened or closed.OnChangeFn<boolean> | undefined
onOpenChangeComplete bits-ui A callback that is called when the menu is opened or closed.OnChangeFn<boolean> | undefined
open bits-ui The open state of the menu.boolean | undefined

ContextMenu.Trigger

PropTypeDefault
class Extra classes merged onto the trigger region.string
child bits-ui Snippet<[{ props: Record<string, unknown>; }]> | undefined
children bits-ui Snippet<[]> | undefined
disabled bits-ui Whether the context menu trigger is disabled. If disabled, the trigger will not open the menu when right-clicked.boolean | undefined
id bits-ui string | undefined
ref bits-ui HTMLElement | null | undefined

ContextMenu.Content

PropTypeDefault
class Extra classes merged onto the menu panel.string
align bits-ui The preferred alignment of the anchor to render against when open. This may change when collisions occur."start" | "center" | "end" | undefined
alignOffset bits-ui An offset in pixels from the "start" or "end" alignment options.number | undefined
arrowPadding bits-ui This describes the padding between the arrow and the edges of the floating element. If your floating element has border-radius, this will prevent it from overflowing the corners.number | undefined
avoidCollisions bits-ui When `true`, overrides the `side` and `align` options to prevent collisions with the boundary edges.boolean | undefinedtrue
child bits-ui Snippet<[FloatingContentSnippetProps & { props: Record<string, unknown>; }]> | undefined
children bits-ui Snippet<[]> | undefined
collisionBoundary bits-ui A boundary element or array of elements to check for collisions against.Arrayable<Boundary> | undefined
collisionPadding bits-ui The amount in pixels of virtual padding around the viewport edges to check for overflow which will cause a collision.number | Partial<Record<"top" | "right" | "bottom" | "left", number>> | undefined8
customAnchor bits-ui Use an element other than the trigger to anchor the content to. If provided, the content will be anchored to the provided element instead of the trigger. You can pass a selector string or an HTMLElement.string | HTMLElement | Measurable | null | undefined
dir bits-ui The text direction of the content.Direction | undefined
escapeKeydownBehavior bits-ui Escape behavior type. `close`: Closes the element immediately. `defer-otherwise-close`: Delegates the action to its parent component that has an escape keydown handler. If no parent is found, it closes the element. `defer-otherwise-ignore`: Delegates the action to the parent element. If no parent is found, nothing is done. `ignore`: Prevents the element from closing and also blocks the parent element from closing in response to an escape key press.EscapeBehaviorType | undefined`close`
forceMount bits-ui Whether to force mount the component.boolean | undefined
hideWhenDetached bits-ui boolean | undefined
id bits-ui string | undefined
interactOutsideBehavior bits-ui Interact outside behavior type. `close`: Closes the element immediately. `defer-otherwise-close`: Delegates the action to the parent element. If no parent is found, it closes the element. `defer-otherwise-ignore`: Delegates the action to the parent element. If no parent is found, nothing is done. `ignore`: Prevents the element from closing and also blocks the parent element from closing in response to an outside interaction.InteractOutsideBehaviorType | undefined`close`
loop bits-ui When `true`, the menu will loop through items when navigating with the keyboard.boolean | undefinedfalse
onCloseAutoFocus bits-ui Event handler called when auto-focusing on close. Can be prevented.EventCallback | undefined
onEscapeKeydown bits-ui Callback fired when escape is pressed.((e: KeyboardEvent) => void) | undefined
onFocusOutside bits-ui Callback fired when focus leaves the dismissible layer.((event: FocusEvent) => void) | undefined
onInteractOutside bits-ui Callback fired when an outside interaction event completes, which is either a `pointerup`, `mouseup`, or `touchend` event, depending on the user's input device.InteractOutsideEventHandler | undefined
onOpenAutoFocus bits-ui Event handler called when auto-focusing on open. Can be prevented.EventCallback | undefined
preventOverflowTextSelection bits-ui Passing `true` will prevent the overflow of text selection outside the element, provided the element is the top layer.boolean | undefined`true`
preventScroll bits-ui Whether to prevent scrolling the body when the content is open. Whether to prevent body scrolling when the content is open.boolean | undefinedtrue
ref bits-ui HTMLElement | null | undefined
side bits-ui The preferred side of the anchor to render against when open. Will be reversed when collisions occur."top" | "right" | "bottom" | "left" | undefined
sideOffset bits-ui The distance in pixels from the anchor to the floating element.number | undefined
sticky bits-ui "partial" | "always" | undefined
strategy bits-ui The positioning strategy to use for the floating element."absolute" | "fixed" | undefined
trapFocus bits-ui Whether focus is trapped within the focus scope.boolean | undefinedfalse
updatePositionStrategy bits-ui "optimized" will only update the position when necessary, while "always" will update the position on each animation frame, which is useful if the floating content is following something like a mouse cursor."always" | "optimized" | undefined"optimized"

ContextMenu.Item (shared)

PropTypeDefault
class Extra classes merged onto the item.string
child bits-ui Snippet<[{ props: Record<string, unknown>; }]> | undefined
children bits-ui Snippet<[]> | undefined
closeOnSelect bits-ui Whether or not the menu item should close when selected.boolean | undefinedtrue
disabled bits-ui When `true`, the user will not be able to interact with the menu item.boolean | undefinedfalse
id bits-ui string | undefined
onSelect bits-ui A callback fired when the menu item is selected. Prevent default behavior of selection with `event.preventDefault()`.((event: Event) => void) | undefined
ref bits-ui HTMLElement | null | undefined
textValue bits-ui Optional text to use for typeahead filtering. By default, typeahead will use the `.textContent` of the menu item. When the content is more complex, you can provide a string here instead.string | undefinedundefined

Root, Sub, SubTrigger, SubContent, CheckboxItem, RadioItem, RadioGroup and Arrow are re-exported from Bits unchanged.

ContextMenu.Trigger

ContextMenu.Content

ContextMenu.Item — shared with Dropdown Menu.