GitHub

Context Menu

A menu triggered by right-click or long-press, providing contextual actions.

Basic Usage

Right-click the area below

Right click here
Context MenuRight-click triggered menu

Installation

pnpm add @corew500/ui

Usage

import {
  ContextMenu,
  ContextMenuTrigger,
  ContextMenuContent,
  ContextMenuItem,
} from "@mordecai-design-system/ui"
<ContextMenu>
  <ContextMenuTrigger>Right-click here</ContextMenuTrigger>
  <ContextMenuContent>
    <ContextMenuItem>Cut</ContextMenuItem>
    <ContextMenuItem>Copy</ContextMenuItem>
    <ContextMenuItem>Paste</ContextMenuItem>
  </ContextMenuContent>
</ContextMenu>

Examples

With Groups

<ContextMenuContent>
  <ContextMenuGroup>
    <ContextMenuLabel>Edit</ContextMenuLabel>
    <ContextMenuItem>Cut</ContextMenuItem>
    <ContextMenuItem>Copy</ContextMenuItem>
  </ContextMenuGroup>
  <ContextMenuSeparator />
  <ContextMenuGroup>
    <ContextMenuLabel>View</ContextMenuLabel>
    <ContextMenuItem>Zoom In</ContextMenuItem>
    <ContextMenuItem>Zoom Out</ContextMenuItem>
  </ContextMenuGroup>
</ContextMenuContent>

With Submenus

<ContextMenuContent>
  <ContextMenuItem>Back</ContextMenuItem>
  <ContextMenuSub>
    <ContextMenuSubTrigger>More Tools</ContextMenuSubTrigger>
    <ContextMenuSubContent>
      <ContextMenuItem>Save As...</ContextMenuItem>
      <ContextMenuItem>Print...</ContextMenuItem>
    </ContextMenuSubContent>
  </ContextMenuSub>
</ContextMenuContent>

With Checkboxes

const [showGrid, setShowGrid] = useState(true)

<ContextMenuCheckboxItem
  checked={showGrid}
  onCheckedChange={setShowGrid}
>
  Show Grid
</ContextMenuCheckboxItem>

With Radio Items

const [theme, setTheme] = useState("light")

<ContextMenuRadioGroup value={theme} onValueChange={setTheme}>
  <ContextMenuRadioItem value="light">Light</ContextMenuRadioItem>
  <ContextMenuRadioItem value="dark">Dark</ContextMenuRadioItem>
  <ContextMenuRadioItem value="system">System</ContextMenuRadioItem>
</ContextMenuRadioGroup>

Destructive Items

<ContextMenuItem variant="destructive">
  Delete
</ContextMenuItem>

Sub-components

| Component | Description | |-----------|-------------| | ContextMenu | Root component | | ContextMenuTrigger | Area that triggers on right-click | | ContextMenuContent | The menu popup | | ContextMenuItem | Clickable menu item | | ContextMenuCheckboxItem | Checkable menu item | | ContextMenuRadioGroup | Group of radio items | | ContextMenuRadioItem | Selectable radio item | | ContextMenuLabel | Non-interactive label | | ContextMenuSeparator | Visual divider | | ContextMenuShortcut | Keyboard shortcut hint | | ContextMenuGroup | Grouping container | | ContextMenuSub | Submenu container | | ContextMenuSubTrigger | Submenu trigger | | ContextMenuSubContent | Submenu content |

Props

ContextMenuItem

PropTypeDefaultDescription
onClickMouseEventHandler<HTMLElement>The click handler for the menu item.
disabledenumfalseWhether the component should ignore user interaction.
labelstringOverrides the text label to use when the item is matched during keyboard text navigation.
idstring@ignore
closeOnClickenumtrueWhether to close the menu when the item is clicked.
nativeButtonenumfalseWhether 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.
styleenumStyle applied to the element, or a function that returns a style object based on the component’s state.
classNameenumCSS class applied to the element, or a function that returns a class based on the component’s state.
renderenumAllows 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.
insetenum
variantenumdefault

ContextMenuContent

PropTypeDefaultDescription
idstring@ignore
finalFocusenumDetermines the element to focus when the menu is closed. - `false`: Do not move focus. - `true`: Move focus based on the default behavior (trigger or previously focused element). - `RefObject`: Move focus to the ref element. - `function`: Called with the interaction type (`mouse`, `touch`, `pen`, or `keyboard`). Return an element to focus, `true` to use the default behavior, or `false`/`undefined` to do nothing.
styleenumStyle applied to the element, or a function that returns a style object based on the component’s state.
classNameenumCSS class applied to the element, or a function that returns a class based on the component’s state.
renderenumAllows 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.
alignenumstartHow to align the popup relative to the specified side.
alignOffsetenum4Additional 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: - `data.anchor`: the dimensions of the anchor element with properties `width` and `height`. - `data.positioner`: the dimensions of the positioner element with properties `width` and `height`. - `data.side`: which side of the anchor element the positioner is aligned against. - `data.align`: how the positioner is aligned relative to the specified side. @example ```jsx <Positioner alignOffset={({ side, align, anchor, positioner }) => { return side === 'top' || side === 'bottom' ? anchor.width : anchor.height; }} /> ```
sideenumrightWhich side of the anchor element to align the popup against. May automatically change to avoid collisions.
sideOffsetenum0Distance 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: - `data.anchor`: the dimensions of the anchor element with properties `width` and `height`. - `data.positioner`: the dimensions of the positioner element with properties `width` and `height`. - `data.side`: which side of the anchor element the positioner is aligned against. - `data.align`: how the positioner is aligned relative to the specified side. @example ```jsx <Positioner sideOffset={({ side, align, anchor, positioner }) => { return side === 'top' || side === 'bottom' ? anchor.height : anchor.width; }} /> ```