@biem/ui

Context Menu

A menu that users open with a right-click or a long press on an area.

A context menu opens at the pointer when users right-click an area or long-press it on a touch screen. It offers the actions that belong to that area, so users act on an entry without moving to a toolbar. An item runs an action, toggles an option, selects one of several values or opens a submenu. A ContextMenuLabel needs a ContextMenuGroup or a ContextMenuRadioGroup around it and names that group for assistive technology.

Right-click transfer 4821

Usage

context-menu-default.tsx
import {
	ContextMenu,
	ContextMenuContent,
	ContextMenuItem,
	ContextMenuTrigger,
} from "@biem/ui/components/ui/context-menu";

export function ContextMenuDefault() {
	return (
		<div className="w-full max-w-sm">
			<ContextMenu>
				<ContextMenuTrigger>
					<div className="flex h-36 items-center justify-center rounded-lg border border-dashed text-sm text-muted-foreground">
						Right-click transfer 4821
					</div>
				</ContextMenuTrigger>
				<ContextMenuContent>
					<ContextMenuItem>Open transfer</ContextMenuItem>
					<ContextMenuItem>Edit quantity</ContextMenuItem>
					<ContextMenuItem>Print packing list</ContextMenuItem>
				</ContextMenuContent>
			</ContextMenu>
		</div>
	);
}

Examples

Destructive

Cancelling an order or discarding a stock count often cannot be reversed. Inside the menu, variant set to "destructive" signals that consequence, so users recognize the risk of an item before they choose it.

Right-click transfer 4821

With Icons

Menus that users open many times a day benefit from a visual anchor for each action. An icon lets users find a familiar action at a glance, while the label still names the outcome and keeps the action clear wherever the icon alone would leave doubt.

Right-click transfer 4821

Inset

Not every action has a fitting icon. With inset, an item without one and the label of its group begin their text where the items with an icon begin theirs, so users scan every label along one line.

Right-click transfer 4821

With Shortcuts

Frequent actions deserve a faster route than the menu. Shown in the menu, a shortcut teaches users the key combination of an item, so next time they trigger the action straight from the keyboard. Responding to those keys remains the task of the application, since the shortcut only displays them.

Right-click transfer 4821

With Separator

When a menu mixes actions of different kinds, such as viewing an entry and changing it, users take it in faster in sections. Each separator sets one section apart from the next and marks the boundary for assistive technology as well.

Right-click transfer 4821

With Groups

Some menus gather actions that concern different things, such as a product and the supplier that delivers it. A ContextMenuGroup with a ContextMenuLabel gives each set a name, so users know what its actions refer to, and assistive technology names the group the same way.

Right-click transfer 4821

With Submenu

Related actions, such as the formats in which a list can be exported, would lengthen the menu if each stood on its own. Collected in a submenu, they appear only once users rest the pointer on its trigger, click it or reach it with the keyboard, and the main menu stays short.

Right-click transfer 4821

With Checkbox Items

Several options can apply to one entry at the same time, and users switch each of them on or off independently. The menu stays open after every change, so users adjust them all in one pass, and through defaultChecked an option starts out switched on.

Right-click transfer 4821

With Radio Items

Some settings hold exactly one value out of several, such as the unit in which a stock list shows its quantities. Selecting a radio item replaces the previous choice, and the menu stays open so users see the result. Through defaultValue, the radio group starts with a value already selected.

Right-click transfer 4821

Top Side

Areas close to the lower edge of a screen, such as a bar with totals, leave little room below the pointer. Set to "top", side opens the menu above the pointer, where the space is.

Right-click transfer 4821

Bottom Side

Headers of tables and pages sit at the top of a screen and lead into the content below them. Through side set to "bottom", the menu opens beneath the spot users clicked, toward the content its actions concern.

Right-click transfer 4821

Left Side

Along the right edge of a screen, such as in a side panel, little room remains to the right of the pointer. Set to "left", side opens the menu on the other side of the pointer, toward the middle of the screen.

Right-click transfer 4821

Right Side

Most areas offer enough room to the right of the pointer, where the menu opens by default. The value "right" of side states this placement explicitly.

Right-click transfer 4821

Controlled

A list whose figures update live should stay still while users choose an action for one of its entries. With open and onOpenChange, the application holds the open state of the menu, so it knows when to pause the updates and can close the menu itself once the entry changes.

Right-click transfer 4821

Controlled Submenu

Options inside a submenu sometimes depend on data worth loading only on demand, such as the warehouses that currently hold stock of a product. Because ContextMenuSub accepts open and onOpenChange, the application knows when users open the submenu and fetches that data at the right moment.

Right-click transfer 4821

Controlled Checkbox Item

An option in the menu often mirrors a setting that also appears elsewhere, such as a flag in the detail view of an order. Once the item receives checked and onCheckedChange, the application holds its state, so both places always agree and the change can be saved at once.

Right-click transfer 4821

Controlled Radio Group

Choices made in the menu can take effect right away, such as the priority that decides when the warehouse picks an order. Through value and onValueChange on the radio group, the application holds the selected value and passes each new choice on without delay.

Right-click transfer 4821

Disabled

While an entry is locked, for example because another user is editing it, its actions do not apply. Set on the context menu, disabled keeps it from opening, and a right-click then brings up the menu of the browser instead.

Right-click transfer 4821

Disabled Item

Individual actions may not apply to an entry yet, such as booking a delivery that has not arrived. The item keeps its place with disabled, so users learn that the action exists, yet it cannot be chosen and assistive technology announces it as unavailable.

Right-click transfer 4821

Disabled Submenu Trigger

Sometimes a whole set of related actions is out of reach, such as exporting a report before its figures are complete. A submenu trigger with disabled no longer opens its submenu, while users still see that these actions exist.

Right-click transfer 4821

Disabled Radio Group

After an order has been released to the warehouse, its delivery method is fixed. With disabled on the radio group, users still see the value that applies, but none of the radio items accepts another choice.

Right-click transfer 4821

API Reference

ContextMenu

Propopen
Typeboolean
Default–
DescriptionSets whether the context menu is open and makes it controlled. Update it in onOpenChange.
PropdefaultOpen
Typeboolean
Defaultfalse
DescriptionOpens the context menu at first render. The context menu then tracks its open state itself.
ProponOpenChange
Type(open: boolean, eventDetails: ContextMenuRootChangeEventDetails) => void
Default–
DescriptionRuns when users open or close the context menu. It receives the open state that follows.
ProponOpenChangeComplete
Type(open: boolean) => void
Default–
DescriptionRuns after the context menu has opened or closed and its animations have finished.
Propdisabled
Typeboolean
Defaultfalse
DescriptionPrevents users from opening the context menu. A right-click on the trigger then opens the menu of the browser.
ProploopFocus
Typeboolean
Defaulttrue
DescriptionMoves the highlight back to the first item when users pass the last one with the arrow keys.
ProphighlightItemOnHover
Typeboolean
Defaulttrue
DescriptionHighlights an item when the pointer moves over it. Set it to false to style hover apart from the keyboard highlight.
Proporientation
Type"horizontal" | "vertical"
Default"vertical"
DescriptionSets whether the up and down or the left and right arrow keys move through the items.
PropactionsRef
TypeRefObject<ContextMenuRootActions | null>
Default–
DescriptionReceives the functions close and unmount. close closes the context menu from code, and unmount removes it from the DOM after a closing animation that the code controls itself.

ContextMenuPortal

PropkeepMounted
Typeboolean
Defaultfalse
DescriptionKeeps the portal in the DOM while the context menu is closed.
Propcontainer
TypeHTMLElement | ShadowRoot | RefObject<HTMLElement | ShadowRoot | null> | null
Default–
DescriptionSets the element that the portal is rendered into. Without it, the portal is appended to the body.
Proprender
TypeReactElement | render function
Default–
DescriptionReplaces the native element or composes the portal with another component.

ContextMenuTrigger

Proprender
TypeReactElement | render function
Default–
DescriptionReplaces the native element or composes the trigger with another component.

ContextMenuContent

Propside
Type"top" | "bottom" | "left" | "right" | "inline-end" | "inline-start"
Default"right"
DescriptionSets the side of the pointer that the menu opens on. inline-end and inline-start follow the text direction. Near the edge of the viewport, the menu shifts to stay visible.
Propalign
Type"start" | "center" | "end"
Default"start"
DescriptionSets whether the start, the center or the end of the menu lines up with the pointer.
PropsideOffset
Typenumber | OffsetFunction
Default0
DescriptionSets the distance between the pointer and the menu in pixels. A function receives the side, the alignment and the dimensions of the anchor and the positioner, and returns the distance.
PropalignOffset
Typenumber | OffsetFunction
Default4
DescriptionMoves the menu along the alignment axis by a number of pixels. A function receives the same data as the one for sideOffset and returns the offset.
PropfinalFocus
Typeboolean | RefObject<HTMLElement | null> | ((closeType: InteractionType) => boolean | HTMLElement | null | void)
Default–
DescriptionDetermines the element that receives focus when the context menu closes. Without it, focus returns to the trigger or to the element that had focus before.
Proprender
TypeReactElement | render function
Default–
DescriptionReplaces the native element or composes the content with another component.

ContextMenuGroup

Proprender
TypeReactElement | render function
Default–
DescriptionReplaces the native element or composes the group with another component.

ContextMenuLabel

Propinset
Typeboolean
Default–
DescriptionIndents the label, so that its text lines up with the text of items that have an icon.
Proprender
TypeReactElement | render function
Default–
DescriptionReplaces the native element or composes the label with another component.

ContextMenuItem

Propvariant
Type"default" | "destructive"
Default"default"
DescriptionSets the color of the item. Destructive colors the text and the icon of an action that deletes something or cannot be undone.
Propinset
Typeboolean
Default–
DescriptionIndents the item, so that its text lines up with the text of items that have an icon.
ProponClick
Type(event: BaseUIEvent<MouseEvent<HTMLDivElement>>) => void
Default–
DescriptionRuns when users choose the item.
PropcloseOnClick
Typeboolean
Defaulttrue
DescriptionCloses the context menu when users choose the item.
Propdisabled
Typeboolean
Defaultfalse
DescriptionPrevents users from choosing the item and exposes the disabled state to assistive technology.
Proplabel
Typestring
Default–
DescriptionSets the text that finds the item when users type its first letters. Without it, the text of the item is used.
Proprender
TypeReactElement | render function
Default–
DescriptionReplaces the native element or composes the item with another component.
PropnativeButton
Typeboolean
Defaultfalse
DescriptionDeclares whether the rendered element is a native button. Set it to true when render returns a button.

ContextMenuSub

Propopen
Typeboolean
Default–
DescriptionSets whether the submenu is open and makes it controlled. Update it in onOpenChange.
PropdefaultOpen
Typeboolean
Defaultfalse
DescriptionOpens the submenu at first render. The submenu then tracks its open state itself.
ProponOpenChange
Type(open: boolean, eventDetails: MenuSubmenuRootChangeEventDetails) => void
Default–
DescriptionRuns when users open or close the submenu. It receives the open state that follows.
ProponOpenChangeComplete
Type(open: boolean) => void
Default–
DescriptionRuns after the submenu has opened or closed and its animations have finished.
Propdisabled
Typeboolean
Defaultfalse
DescriptionPrevents users from opening the submenu.
PropcloseParentOnEsc
Typeboolean
Defaultfalse
DescriptionCloses the whole context menu when users press Escape in the submenu. Without it, Escape closes only the submenu.
ProploopFocus
Typeboolean
Defaulttrue
DescriptionMoves the highlight back to the first item of the submenu when users pass the last one with the arrow keys.
ProphighlightItemOnHover
Typeboolean
Defaulttrue
DescriptionHighlights an item of the submenu when the pointer moves over it. Set it to false to style hover apart from the keyboard highlight.
Proporientation
Type"horizontal" | "vertical"
Default"vertical"
DescriptionSets whether the up and down or the left and right arrow keys move through the items of the submenu.
PropactionsRef
TypeRefObject<MenuRootActions | null>
Default–
DescriptionReceives the functions close and unmount. close closes the submenu from code, and unmount removes it from the DOM after a closing animation that the code controls itself.

ContextMenuSubTrigger

Propinset
Typeboolean
Default–
DescriptionIndents the submenu trigger, so that its text lines up with the text of items that have an icon.
ProponClick
Type(event: BaseUIEvent<MouseEvent<HTMLDivElement>>) => void
Default–
DescriptionRuns when users click the submenu trigger.
PropopenOnHover
Typeboolean
Defaulttrue
DescriptionOpens the submenu when the pointer rests on the submenu trigger. With false, users open the submenu with a click or with the keyboard.
Propdelay
Typenumber
Default100
DescriptionSets how many milliseconds the pointer rests on the submenu trigger before the submenu opens. It has no effect without openOnHover.
PropcloseDelay
Typenumber
Default0
DescriptionSets how many milliseconds a submenu that was opened by hover waits before it closes. It has no effect without openOnHover.
Propdisabled
Typeboolean
Defaultfalse
DescriptionPrevents users from opening the submenu with this trigger.
Proplabel
Typestring
Default–
DescriptionSets the text that finds the submenu trigger when users type its first letters. Without it, the text of the submenu trigger is used.
Proprender
TypeReactElement | render function
Default–
DescriptionReplaces the native element or composes the submenu trigger with another component.
PropnativeButton
Typeboolean
Defaultfalse
DescriptionDeclares whether the rendered element is a native button. Set it to true when render returns a button.

ContextMenuSubContent

Propside
Type"top" | "bottom" | "left" | "right" | "inline-end" | "inline-start"
Default"right"
DescriptionSets the side of the submenu trigger that the submenu opens on. inline-end and inline-start follow the text direction. The submenu switches to the opposite side when it doesn't fit.
Propalign
Type"start" | "center" | "end"
Default"start"
DescriptionSets whether the start, the center or the end of the submenu lines up with the submenu trigger.
PropsideOffset
Typenumber | OffsetFunction
Default0
DescriptionSets the distance between the submenu trigger and the submenu in pixels. A function receives the side, the alignment and the dimensions of the anchor and the positioner, and returns the distance.
PropalignOffset
Typenumber | OffsetFunction
Default4
DescriptionMoves the submenu along the alignment axis by a number of pixels. A function receives the same data as the one for sideOffset and returns the offset.
PropfinalFocus
Typeboolean | RefObject<HTMLElement | null> | ((closeType: InteractionType) => boolean | HTMLElement | null | void)
Default–
DescriptionDetermines the element that receives focus when the submenu closes. Without it, focus returns to the trigger or to the element that had focus before.
Proprender
TypeReactElement | render function
Default–
DescriptionReplaces the native element or composes the submenu content with another component.

ContextMenuCheckboxItem

Propchecked
Typeboolean
Default–
DescriptionSets whether the item is checked and makes it controlled. Update it in onCheckedChange.
PropdefaultChecked
Typeboolean
Defaultfalse
DescriptionChecks the item at first render. The item then tracks its state itself.
ProponCheckedChange
Type(checked: boolean, eventDetails: MenuCheckboxItemChangeEventDetails) => void
Default–
DescriptionRuns when users check or uncheck the item. It receives the state that follows.
Propinset
Typeboolean
Default–
DescriptionIndents the item, so that its text lines up with the text of items that have an icon.
ProponClick
Type(event: BaseUIEvent<MouseEvent<HTMLDivElement>>) => void
Default–
DescriptionRuns when users click the item.
PropcloseOnClick
Typeboolean
Defaultfalse
DescriptionCloses the context menu when users check or uncheck the item.
Propdisabled
Typeboolean
Defaultfalse
DescriptionPrevents users from checking or unchecking the item and exposes the disabled state to assistive technology.
Proplabel
Typestring
Default–
DescriptionSets the text that finds the item when users type its first letters. Without it, the text of the item is used.
Proprender
TypeReactElement | render function
Default–
DescriptionReplaces the native element or composes the item with another component.
PropnativeButton
Typeboolean
Defaultfalse
DescriptionDeclares whether the rendered element is a native button. Set it to true when render returns a button.

ContextMenuRadioGroup

Propvalue
Typeany
Default–
DescriptionSets the value of the selected radio item and makes the radio group controlled. Update it in onValueChange.
PropdefaultValue
Typeany
Default–
DescriptionSets the value of the radio item that is selected at first render. The radio group then tracks the selection itself.
ProponValueChange
Type(value: any, eventDetails: MenuRadioGroupChangeEventDetails) => void
Default–
DescriptionRuns when users select a radio item. It receives the value of that item.
Propdisabled
Typeboolean
Defaultfalse
DescriptionPrevents users from selecting any radio item of the group.
Proprender
TypeReactElement | render function
Default–
DescriptionReplaces the native element or composes the radio group with another component.

ContextMenuRadioItem

Propvalue
Typeany
Default–
DescriptionSets the value that the radio group holds while this item is selected. Every radio item needs one.
Propinset
Typeboolean
Default–
DescriptionIndents the item, so that its text lines up with the text of items that have an icon.
ProponClick
Type(event: BaseUIEvent<MouseEvent<HTMLDivElement>>) => void
Default–
DescriptionRuns when users click the item.
PropcloseOnClick
Typeboolean
Defaultfalse
DescriptionCloses the context menu when users select the item.
Propdisabled
Typeboolean
Defaultfalse
DescriptionPrevents users from selecting the item and exposes the disabled state to assistive technology.
Proplabel
Typestring
Default–
DescriptionSets the text that finds the item when users type its first letters. Without it, the text of the item is used.
Proprender
TypeReactElement | render function
Default–
DescriptionReplaces the native element or composes the item with another component.
PropnativeButton
Typeboolean
Defaultfalse
DescriptionDeclares whether the rendered element is a native button. Set it to true when render returns a button.

ContextMenuSeparator

Proporientation
Type"horizontal" | "vertical"
Default"horizontal"
DescriptionSets the orientation that the separator exposes to assistive technology. The line itself stays horizontal.
Proprender
TypeReactElement | render function
Default–
DescriptionReplaces the native element or composes the separator with another component.

ContextMenuShortcut

ContextMenuShortcut shows the key combination of an item at the end of its row, and the application handles the keys itself. It renders a span and has no props of its own.