Usage
import { ContextMenu } from "@voila.dev/ui/context-menu";<ContextMenu.Root>
<ContextMenu.Trigger className="…">Right-click here</ContextMenu.Trigger>
<ContextMenu.Content>
<ContextMenu.Item>Edit project</ContextMenu.Item>
<ContextMenu.Separator />
<ContextMenu.Item variant="destructive">Cancel project</ContextMenu.Item>
</ContextMenu.Content>
</ContextMenu.Root>The same menu as DropdownMenu, opened by right-click on a region rather than by a button. That trigger is its whole problem: nothing on screen advertises it, and it does not exist on touch. So a context menu may accelerate an action but must never be its only route — put the same items in a visible menu too.
Recipes
The parts mirror DropdownMenu exactly — Group,
Separator, Sub, CheckboxItem, RadioItem, Shortcut, and the same inset
and variant="destructive" on items. Anything you learn on one page applies to
the other.
API
ContextMenu.Root
| Prop | Type | Default | |
|---|---|---|---|
actionsRef | RefObject<MenuRootActions | null> | — | A ref to imperative actions. |
children | PayloadChildRenderFunction<unknown> | ReactNode | — | The content of the popover.
This can be a regular React node or a render function that receives the payload of the active trigger. |
closeParentOnEsc | boolean | — | When in a submenu, determines whether pressing the Escape key closes the entire menu, or only the current child menu. |
defaultOpen | boolean | — | Whether the menu is initially open. To render a controlled menu, use the open prop instead. |
defaultTriggerId | string | null | — | ID of the trigger that the popover is associated with.
This is useful in conjunction with the defaultOpen prop to create an initially open popover. |
disabled | boolean | — | Whether the component should ignore user interaction. |
handle | MenuHandle<unknown> | — | A handle to associate the menu with a trigger. If specified, allows external triggers to control the menu's open state. |
highlightItemOnHover | boolean | — | Whether moving the pointer over items should highlight them.
Disabling this prop allows CSS :hover to be differentiated from the :focus (data-highlighted) state. |
loopFocus | boolean | — | Whether to loop keyboard focus back to the first item when the end of the list is reached while using the arrow keys. |
onOpenChange | ((open: boolean, eventDetails: ContextMenuRootChangeEventDetails) => void) | — | Event handler called when the menu is opened or closed. |
onOpenChangeComplete | ((open: boolean) => void) | — | Event handler called after any animations complete when the menu is closed. |
open | boolean | — | Whether the menu is currently open. |
orientation | MenuRootOrientation | — | The visual orientation of the menu. Controls whether roving focus uses up/down or left/right arrow keys. |
triggerId | string | null | — | ID of the trigger that the popover is associated with.
This is useful in conjunction with the open prop to create a controlled popover.
There's no need to specify this prop when the popover is uncontrolled (that is, when the open prop is not set). |
Plus the DOM props of the element it renders. Source: context-menu/components/context-menu-root.tsx.
ContextMenu.CheckboxItem
| Prop | Type | Default | |
|---|---|---|---|
inset | boolean | — | Indents the item to line up with siblings that have an icon or a checkmark. |
checked | boolean | — | Whether the checkbox item is currently ticked. To render an uncontrolled checkbox item, use the defaultChecked prop instead. |
className | string | ((state: MenuCheckboxItemState) => string | undefined) | — | CSS class applied to the element, or a function that returns a class based on the component's state. |
closeOnClick | boolean | — | Whether to close the menu when the item is clicked. |
defaultChecked | boolean | — | Whether the checkbox item is initially ticked. To render a controlled checkbox item, use the checked prop instead. |
disabled | boolean | — | Whether the component should ignore user interaction. |
id | string | — | |
label | string | — | Overrides the text label to use when the item is matched during keyboard text navigation. |
nativeButton | boolean | — | Whether the component renders a native <button> element when replacing it
via the render prop.
Set to true if the rendered element is a native button. |
onCheckedChange | ((checked: boolean, eventDetails: MenuRootChangeEventDetails) => void) | — | Event handler called when the checkbox item is ticked or unticked. |
onClick | ((event: BaseUIEvent<MouseEvent<HTMLDivElement, MouseEvent>>) => void) | — | The click handler for the menu item. |
render | ComponentRenderFn<HTMLProps, MenuCheckboxItemState> | ReactElement<unknown, string | JSXElementConstructor<any>> | — | Allows you to replace the component's HTML element
with a different tag, or compose it with another component. Accepts a ReactElement or a function that returns the element to render. |
style | CSSProperties | ((state: MenuCheckboxItemState) => CSSProperties | undefined) | — | Style applied to the element, or a function that returns a style object based on the component's state. |
Plus the DOM props of the element it renders. Source: context-menu/components/context-menu-checkbox-item.tsx.
ContextMenu.Content
| Prop | Type | Default | |
|---|---|---|---|
align | Align | "start" | How to align the popup relative to the specified side. |
alignOffset | number | OffsetFunction | 4 | Additional offset along the alignment axis in pixels.
Also accepts a function that returns the offset to read the dimensions of the anchor
and positioner elements, along with its side and alignment. The function takes a data object parameter with the following properties: |
children | ReactNode | — | |
className | string | ((state: MenuPopupState) => string | undefined) | — | CSS class applied to the element, or a function that returns a class based on the component's state. |
finalFocus | boolean | RefObject<HTMLElement | null> | ((closeType: InteractionType) => void | boolean | HTMLElement | null) | — | Determines the element to focus when the menu is closed. |
id | string | — | |
render | ComponentRenderFn<HTMLProps, MenuPopupState> | ReactElement<unknown, string | JSXElementConstructor<any>> | — | Allows you to replace the component's HTML element
with a different tag, or compose it with another component. Accepts a ReactElement or a function that returns the element to render. |
side | Side | "right" | Which side of the anchor element to align the popup against. May automatically change to avoid collisions. |
sideOffset | number | OffsetFunction | 0 | Distance between the anchor and the popup in pixels.
Also accepts a function that returns the distance to read the dimensions of the anchor
and positioner elements, along with its side and alignment. The function takes a data object parameter with the following properties: |
style | CSSProperties | ((state: MenuPopupState) => CSSProperties | undefined) | — | Style applied to the element, or a function that returns a style object based on the component's state. |
Plus the DOM props of the element it renders. Source: context-menu/components/context-menu-content.tsx.
ContextMenu.Group
| Prop | Type | Default | |
|---|---|---|---|
children | ReactNode | — | The content of the component. |
className | string | ((state: MenuGroupState) => string | undefined) | — | CSS class applied to the element, or a function that returns a class based on the component's state. |
render | ComponentRenderFn<HTMLProps, MenuGroupState> | ReactElement<unknown, string | JSXElementConstructor<any>> | — | Allows you to replace the component's HTML element
with a different tag, or compose it with another component. Accepts a ReactElement or a function that returns the element to render. |
style | CSSProperties | ((state: MenuGroupState) => CSSProperties | undefined) | — | Style applied to the element, or a function that returns a style object based on the component's state. |
Plus the DOM props of the element it renders. Source: context-menu/components/context-menu-group.tsx.
ContextMenu.Item
| Prop | Type | Default | |
|---|---|---|---|
inset | boolean | — | Indents the item to line up with siblings that have an icon or a checkmark. |
variant | "default" | "destructive" | "default" | destructive tints the item red, for the one action that deletes something. |
className | string | ((state: MenuItemState) => string | undefined) | — | CSS class applied to the element, or a function that returns a class based on the component's state. |
closeOnClick | boolean | — | Whether to close the menu when the item is clicked. |
disabled | boolean | — | Whether the component should ignore user interaction. |
id | string | — | |
label | string | — | Overrides the text label to use when the item is matched during keyboard text navigation. |
nativeButton | boolean | — | Whether the component renders a native <button> element when replacing it
via the render prop.
Set to true if the rendered element is a native button. |
onClick | ((event: BaseUIEvent<MouseEvent<HTMLDivElement, MouseEvent>>) => void) | — | The click handler for the menu item. |
render | ComponentRenderFn<HTMLProps, MenuItemState> | ReactElement<unknown, string | JSXElementConstructor<any>> | — | Allows you to replace the component's HTML element
with a different tag, or compose it with another component. Accepts a ReactElement or a function that returns the element to render. |
style | CSSProperties | ((state: MenuItemState) => CSSProperties | undefined) | — | Style applied to the element, or a function that returns a style object based on the component's state. |
Plus the DOM props of the element it renders. Source: context-menu/components/context-menu-item.tsx.
ContextMenu.Label
| Prop | Type | Default | |
|---|---|---|---|
inset | boolean | — | Indents the item to line up with siblings that have an icon or a checkmark. |
Plus every <div> prop. Source: context-menu/components/context-menu-label.tsx.
ContextMenu.Portal
| Prop | Type | Default | |
|---|---|---|---|
className | string | ((state: MenuPortalState) => string | undefined) | — | CSS class applied to the element, or a function that returns a class based on the component's state. |
container | HTMLElement | RefObject<HTMLElement | ShadowRoot | null> | ShadowRoot | null | — | A parent element to render the portal element into. |
keepMounted | boolean | — | Whether to keep the portal mounted in the DOM while the popup is hidden. |
render | ComponentRenderFn<HTMLProps, MenuPortalState> | ReactElement<unknown, string | JSXElementConstructor<any>> | — | Allows you to replace the component's HTML element
with a different tag, or compose it with another component. Accepts a ReactElement or a function that returns the element to render. |
style | CSSProperties | ((state: MenuPortalState) => CSSProperties | undefined) | — | Style applied to the element, or a function that returns a style object based on the component's state. |
Plus the DOM props of the element it renders. Source: context-menu/components/context-menu-portal.tsx.
ContextMenu.RadioGroup
| Prop | Type | Default | |
|---|---|---|---|
children | ReactNode | — | The content of the component. |
className | string | ((state: MenuRadioGroupState) => string | undefined) | — | CSS class applied to the element, or a function that returns a class based on the component's state. |
defaultValue | any | — | The uncontrolled value of the radio item that should be initially selected. To render a controlled radio group, use the value prop instead. |
disabled | boolean | — | Whether the component should ignore user interaction. |
onValueChange | ((value: any, eventDetails: MenuRootChangeEventDetails) => void) | — | Function called when the selected value changes. |
render | ComponentRenderFn<HTMLProps, MenuRadioGroupState> | ReactElement<unknown, string | JSXElementConstructor<any>> | — | Allows you to replace the component's HTML element
with a different tag, or compose it with another component. Accepts a ReactElement or a function that returns the element to render. |
style | CSSProperties | ((state: MenuRadioGroupState) => CSSProperties | undefined) | — | Style applied to the element, or a function that returns a style object based on the component's state. |
value | any | — | The controlled value of the radio item that should be currently selected. To render an uncontrolled radio group, use the defaultValue prop instead. |
Plus the DOM props of the element it renders. Source: context-menu/components/context-menu-radio-group.tsx.
ContextMenu.RadioItem
| Prop | Type | Default | |
|---|---|---|---|
inset | boolean | — | Indents the item to line up with siblings that have an icon or a checkmark. |
value | any | required | Value of the radio item. This is the value that will be set in the MenuRadioGroup when the item is selected. |
className | string | ((state: MenuRadioItemState) => string | undefined) | — | CSS class applied to the element, or a function that returns a class based on the component's state. |
closeOnClick | boolean | — | Whether to close the menu when the item is clicked. |
disabled | boolean | — | Whether the component should ignore user interaction. |
id | string | — | |
label | string | — | Overrides the text label to use when the item is matched during keyboard text navigation. |
nativeButton | boolean | — | Whether the component renders a native <button> element when replacing it
via the render prop.
Set to true if the rendered element is a native button. |
onClick | ((event: BaseUIEvent<MouseEvent<HTMLDivElement, MouseEvent>>) => void) | — | The click handler for the menu item. |
render | ComponentRenderFn<HTMLProps, MenuRadioItemState> | ReactElement<unknown, string | JSXElementConstructor<any>> | — | Allows you to replace the component's HTML element
with a different tag, or compose it with another component. Accepts a ReactElement or a function that returns the element to render. |
style | CSSProperties | ((state: MenuRadioItemState) => CSSProperties | undefined) | — | Style applied to the element, or a function that returns a style object based on the component's state. |
Plus the DOM props of the element it renders. Source: context-menu/components/context-menu-radio-item.tsx.
ContextMenu.Separator
| Prop | Type | Default | |
|---|---|---|---|
className | string | ((state: SeparatorState) => string | undefined) | — | CSS class applied to the element, or a function that returns a class based on the component's state. |
orientation | Orientation | — | The orientation of the separator. |
render | ComponentRenderFn<HTMLProps, SeparatorState> | ReactElement<unknown, string | JSXElementConstructor<any>> | — | Allows you to replace the component's HTML element
with a different tag, or compose it with another component. Accepts a ReactElement or a function that returns the element to render. |
style | CSSProperties | ((state: SeparatorState) => CSSProperties | undefined) | — | Style applied to the element, or a function that returns a style object based on the component's state. |
Plus the DOM props of the element it renders. Source: context-menu/components/context-menu-separator.tsx.
ContextMenu.Shortcut
| Prop | Type | Default | |
|---|---|---|---|
keys | readonly string[] | — | Render each key as a small Kbd chip. Omit it and children are shown as plain text. |
Plus the DOM props of the element it renders. Source: context-menu/components/context-menu-shortcut.tsx.
ContextMenu.Sub
| Prop | Type | Default | |
|---|---|---|---|
actionsRef | RefObject<MenuRootActions | null> | — | A ref to imperative actions. |
children | ReactNode | — | The content of the submenu. |
closeParentOnEsc | boolean | — | When in a submenu, determines whether pressing the Escape key closes the entire menu, or only the current child menu. |
defaultOpen | boolean | — | Whether the menu is initially open. To render a controlled menu, use the open prop instead. |
disabled | boolean | — | Whether the component should ignore user interaction. |
highlightItemOnHover | boolean | — | Whether moving the pointer over items should highlight them.
Disabling this prop allows CSS :hover to be differentiated from the :focus (data-highlighted) state. |
loopFocus | boolean | — | Whether to loop keyboard focus back to the first item when the end of the list is reached while using the arrow keys. |
onOpenChange | ((open: boolean, eventDetails: MenuRootChangeEventDetails) => void) | — | Event handler called when the menu is opened or closed. |
onOpenChangeComplete | ((open: boolean) => void) | — | Event handler called after any animations complete when the menu is closed. |
open | boolean | — | Whether the menu is currently open. |
orientation | MenuRootOrientation | — | The visual orientation of the menu. Controls whether roving focus uses up/down or left/right arrow keys. |
Plus the DOM props of the element it renders. Source: context-menu/components/context-menu-sub.tsx.
ContextMenu.SubContent
| Prop | Type | Default | |
|---|---|---|---|
align | Align | — | How to align the popup relative to the specified side. |
alignOffset | number | OffsetFunction | — | Additional offset along the alignment axis in pixels.
Also accepts a function that returns the offset to read the dimensions of the anchor
and positioner elements, along with its side and alignment. The function takes a data object parameter with the following properties: |
children | ReactNode | — | |
className | string | ((state: MenuPopupState) => string | undefined) | — | CSS class applied to the element, or a function that returns a class based on the component's state. |
finalFocus | boolean | RefObject<HTMLElement | null> | ((closeType: InteractionType) => void | boolean | HTMLElement | null) | — | Determines the element to focus when the menu is closed. |
id | string | — | |
render | ComponentRenderFn<HTMLProps, MenuPopupState> | ReactElement<unknown, string | JSXElementConstructor<any>> | — | Allows you to replace the component's HTML element
with a different tag, or compose it with another component. Accepts a ReactElement or a function that returns the element to render. |
side | Side | "right" | Which side of the anchor element to align the popup against. May automatically change to avoid collisions. |
sideOffset | number | OffsetFunction | — | Distance between the anchor and the popup in pixels.
Also accepts a function that returns the distance to read the dimensions of the anchor
and positioner elements, along with its side and alignment. The function takes a data object parameter with the following properties: |
style | CSSProperties | ((state: MenuPopupState) => CSSProperties | undefined) | — | Style applied to the element, or a function that returns a style object based on the component's state. |
Plus the DOM props of the element it renders. Source: context-menu/components/context-menu-sub-content.tsx.
ContextMenu.SubTrigger
| Prop | Type | Default | |
|---|---|---|---|
inset | boolean | — | Indents the item to line up with siblings that have an icon or a checkmark. |
className | string | ((state: MenuSubmenuTriggerState) => string | undefined) | — | CSS class applied to the element, or a function that returns a class based on the component's state. |
closeDelay | number | — | How long to wait before closing the menu that was opened on hover.
Specified in milliseconds. Requires the openOnHover prop. |
delay | number | — | How long to wait before the menu may be opened on hover. Specified in milliseconds. Requires the openOnHover prop. |
disabled | boolean | — | Whether the component should ignore user interaction. |
id | string | — | |
label | string | — | Overrides the text label to use when the item is matched during keyboard text navigation. |
nativeButton | boolean | — | Whether the component renders a native <button> element when replacing it
via the render prop.
Set to true if the rendered element is a native button. |
onClick | ((event: BaseUIEvent<MouseEvent<HTMLDivElement, MouseEvent>>) => void) | — | |
openOnHover | boolean | — | Whether the menu should also open when the trigger is hovered. |
render | ComponentRenderFn<HTMLProps, MenuSubmenuTriggerState> | ReactElement<unknown, string | JSXElementConstructor<any>> | — | Allows you to replace the component's HTML element
with a different tag, or compose it with another component. Accepts a ReactElement or a function that returns the element to render. |
style | CSSProperties | ((state: MenuSubmenuTriggerState) => CSSProperties | undefined) | — | Style applied to the element, or a function that returns a style object based on the component's state. |
Plus the DOM props of the element it renders. Source: context-menu/components/context-menu-sub-trigger.tsx.
ContextMenu.Trigger
| Prop | Type | Default | |
|---|---|---|---|
className | string | ((state: ContextMenuTriggerState) => string | undefined) | — | CSS class applied to the element, or a function that returns a class based on the component's state. |
render | ComponentRenderFn<HTMLProps, ContextMenuTriggerState> | ReactElement<unknown, string | JSXElementConstructor<any>> | — | Allows you to replace the component's HTML element
with a different tag, or compose it with another component. Accepts a ReactElement or a function that returns the element to render. |
style | CSSProperties | ((state: ContextMenuTriggerState) => CSSProperties | undefined) | — | Style applied to the element, or a function that returns a style object based on the component's state. |
Plus the DOM props of the element it renders. Source: context-menu/components/context-menu-trigger.tsx.
Related
DropdownMenu · Menubar · Kbd