Context menu
Menu rows at the pointer, or opened from the keyboard
Files
Right-click a file, or press Shift+F10 on one.
Installation
npx shadcn@latest add @sudokw/components-context-menuimport { ContextMenu } from "@gpuixui/components";Usage
import {
ContextMenu,
ContextMenuCheckboxItem,
ContextMenuContent,
ContextMenuItem,
ContextMenuSeparator,
ContextMenuSub,
ContextMenuSubContent,
ContextMenuSubTrigger,
ContextMenuTrigger,
} from "@gpuixui/components/context-menu";
<ContextMenu>
<ContextMenuTrigger>
<text>release-notes.md</text>
</ContextMenuTrigger>
<ContextMenuContent label="Project actions">
<ContextMenuItem onSelect={open}>Open</ContextMenuItem>
<ContextMenuItem onSelect={rename}>Rename</ContextMenuItem>
<ContextMenuItem disabled>Move to trash</ContextMenuItem>
<ContextMenuSub>
<ContextMenuSubTrigger>Share</ContextMenuSubTrigger>
<ContextMenuSubContent label="Share">
<ContextMenuItem onSelect={copyLink}>Copy link</ContextMenuItem>
<ContextMenuItem onSelect={email}>Email</ContextMenuItem>
</ContextMenuSubContent>
</ContextMenuSub>
<ContextMenuSeparator />
<ContextMenuCheckboxItem
checked={showHidden}
onCheckedChange={setShowHidden}
>
Show hidden files
</ContextMenuCheckboxItem>
</ContextMenuContent>
</ContextMenu>;Composition
ContextMenu
├── ContextMenuTrigger
└── ContextMenuContent
├── ContextMenuItem
├── ContextMenuCheckboxItem
├── ContextMenuRadioGroup
│ └── ContextMenuRadioItem
├── ContextMenuSeparator
├── ContextMenuLabel
├── ContextMenuGroup
└── ContextMenuSub
├── ContextMenuSubTrigger
└── ContextMenuSubContentAPI reference
ContextMenu
| Prop | Type | Default | Consequence |
|---|---|---|---|
open | boolean | uncontrolled | controlled open state |
defaultOpen | boolean | false | the initial state when uncontrolled |
onOpenChange | (open: boolean, details: { reason }) => void | none | reports the next state and why it changed: trigger-press, item-press, escape-key, outside-press, focus-out or pointer-leave; a controlled menu waits for the caller |
children | parts | none | ContextMenuTrigger and ContextMenuContent |
ContextMenuTrigger
| Prop | Type | Default | Consequence |
|---|---|---|---|
disabled | boolean | false | no aux click, no Shift+F10, out of the tab order, dimmed |
children | nodes | none | the area the reader presses |
style | host style | none | merged last over the card-like box |
ContextMenuContent
| Prop | Type | Default | Consequence |
|---|---|---|---|
label | string | "Context menu" | the surface's accessible name |
children | parts | none | rows, groups, labels, separators and submenus |
className | string | none | compiled through @gpuixui/tw and joined after the recipe |
style | host style | none | merged last on the surface |
ContextMenuItem and ContextMenuCheckboxItem
| Prop | Type | Default | Consequence |
|---|---|---|---|
onSelect | () => void | none | runs once when the row is activated |
disabled | boolean | false | skipped by arrows and type-ahead; paints the measured disabled pair |
tone | "default" | "destructive" | "default" — a stored name the union does not carry | a destructive row paints the status tone's readable role |
leading / trailing | ReactNode | none | slots before and after the label |
textValue | string | the label | the text type-ahead searches |
closeOnSelect | boolean | true | whether activation closes the menu |
checked | boolean | none | the checkbox row's state (required on ContextMenuCheckboxItem) |
onCheckedChange | (checked: boolean) => void | none | reported when the checkbox row toggles (required) |
className | string | none | compiled through @gpuixui/tw and joined after the recipe |
style | MenuItemState callback | none | { disabled, highlighted }, merged after the row's roles |
ContextMenuRadioGroup and ContextMenuRadioItem
| Prop | Type | Default | Consequence |
|---|---|---|---|
value | string | none | the chosen row's value (required on the group) |
onValueChange | (value: string) => void | none | reported with a row's value when it is chosen, never the current one (required) |
label | string | none | the choice's accessible name; a painted ContextMenuLabel does not name the group |
className | string | none | compiled through @gpuixui/tw, joined after the recipe |
children | parts | none | the group's ContextMenuRadioItem rows |
value | string | none | this row's value inside the group (required on ContextMenuRadioItem) |
closeOnSelect / disabled / tone / leading / trailing / textValue | as the action row | — | the row's own slots, tone and type-ahead key |
style | MenuRadioItemState callback | none | { checked, disabled, highlighted }, merged after the row's roles |
ContextMenuSub, ContextMenuSubTrigger, ContextMenuSubContent
| Prop | Type | Default | Consequence |
|---|---|---|---|
children | parts | none | ContextMenuSub holds a trigger and its content |
label | string | none | the second level's accessible name |
disabled / leading / trailing / textValue | the row surface | — | the sub trigger is an ordinary row that opens the second level |
className / style | host | none | merged last |
Keyboard
- Shift+F10
- opens the menu at the trigger, as the Menu key does
- Arrow DownArrow UpCtrl+NCtrl+P
- moves the highlighted row
- HomeEnd
- the first or last row
- EnterSpace
- runs the highlighted row
- Escape
- closes the topmost surface
- Tab
- closes the menu and lets focus move on
read from context-menu.tsx, surface.tsx, modal.ts
Edit this page on GitHubapps/docs/content/docs/components/context-menu.mdx