VayuUI

Context Menu

A right-click context menu with items, checkbox items, radio groups, sub-menus, separators, and labels. Fully keyboard-accessible with ARIA roles.

Installation

npx vayu-ui init #one time only
npx vayu-ui add contextmenu
npx vayu-ui add -t contextmenu #with test case needs

Usage

Right-click the area below to open the context menu.

Keyboard shortcuts:

  • ↑/↓ arrows to navigate
  • → to open submenu
  • ← to close submenu
  • Type to search items
  • Home/End to jump
Right-click here

Current State:

Show Bookmarks: true

Show URLs: false

Assignee: andy

<ContextMenu>
  <ContextMenu.Trigger>
    <div>Right-click here</div>
  </ContextMenu.Trigger>

  <ContextMenu.Content>
    <ContextMenu.Item shortcut="⌘Z" onSelect={() => console.log('Undo')}>
      Undo
    </ContextMenu.Item>
    <ContextMenu.Item shortcut="⌘⇧Z" onSelect={() => console.log('Redo')}>
      Redo
    </ContextMenu.Item>

    <ContextMenu.Separator />

    <ContextMenu.Item shortcut="⌘X">Cut</ContextMenu.Item>
    <ContextMenu.Item shortcut="⌘C">Copy</ContextMenu.Item>
    <ContextMenu.Item shortcut="⌘V">Paste</ContextMenu.Item>

    <ContextMenu.Separator />

    <ContextMenu.Sub>
      <ContextMenu.SubTrigger>Export As</ContextMenu.SubTrigger>
      <ContextMenu.SubContent>
        <ContextMenu.Item>PDF Document</ContextMenu.Item>
        <ContextMenu.Item>PNG Image</ContextMenu.Item>
      </ContextMenu.SubContent>
    </ContextMenu.Sub>

    <ContextMenu.Separator />

    <ContextMenu.Label>View Options</ContextMenu.Label>
    <ContextMenu.CheckboxItem checked={showBookmarks} onCheckedChange={setShowBookmarks}>
      Show Bookmarks Bar
    </ContextMenu.CheckboxItem>

    <ContextMenu.Separator />

    <ContextMenu.Label>Assignee</ContextMenu.Label>
    <ContextMenu.RadioGroup value={person} onValueChange={setPerson}>
      <ContextMenu.RadioItem value="andy">Andy</ContextMenu.RadioItem>
      <ContextMenu.RadioItem value="pedro">Pedro</ContextMenu.RadioItem>
    </ContextMenu.RadioGroup>

    <ContextMenu.Separator />

    <ContextMenu.Item destructive>Delete</ContextMenu.Item>
  </ContextMenu.Content>
</ContextMenu>

Anatomy

import { ContextMenu } from 'vayu-ui';

export default () => (
  <ContextMenu>
    <ContextMenu.Trigger>
      <div>Right-click target area</div>
    </ContextMenu.Trigger>
    <ContextMenu.Content>
      <ContextMenu.Label>Section Label</ContextMenu.Label>
      <ContextMenu.Item>Menu Item</ContextMenu.Item>
      <ContextMenu.CheckboxItem checked>Checkbox Item</ContextMenu.CheckboxItem>
      <ContextMenu.Separator />
      <ContextMenu.Sub>
        <ContextMenu.SubTrigger>Submenu Trigger</ContextMenu.SubTrigger>
        <ContextMenu.SubContent>
          <ContextMenu.Item>Sub Item</ContextMenu.Item>
        </ContextMenu.SubContent>
      </ContextMenu.Sub>
      <ContextMenu.RadioGroup value="val">
        <ContextMenu.RadioItem value="val">Radio Item</ContextMenu.RadioItem>
      </ContextMenu.RadioGroup>
    </ContextMenu.Content>
  </ContextMenu>
);

Accessibility

  • Keyboard support: Right-click, Context Menu key, or Shift+F10 opens the menu. ArrowUp/ArrowDown navigates items. Enter or Space selects an item. Escape closes the menu. ArrowRight opens a submenu, ArrowLeft closes it. Home/End jump to first/last item. Type characters to search.
  • ARIA attributes: Uses role="menu", role="menuitem", role="menuitemcheckbox", role="menuitemradio", role="separator", and role="group" for semantic meaning. aria-haspopup, aria-expanded, and aria-checked communicate state.
  • Focus behavior: Focus is trapped within the open menu. First item is auto-focused on open. Focus returns to trigger on close.

Screen reader behavior

Screen readers will announce the component as a "menu" when opened, reading each item with its role, state (checked, disabled), and available keyboard shortcuts. Submenus are announced with expanded/collapsed state to indicate hierarchy. Checkbox items announce their checked state, and radio items communicate selection within the group.

Component Folder Structure

ContextMenu/
├── index.ts
├── types.ts
├── hooks.ts
├── ContextMenu.tsx
├── ContextMenuTrigger.tsx
├── ContextMenuContent.tsx
├── ContextMenuItem.tsx
├── ContextMenuCheckBoxItem.tsx
├── ContextMenuRadioGroup.tsx
├── ContextMenuSub.tsx
├── ContextMenuSeparator.tsx
├── ContextMenuLabel.tsx
└── README.md

Props

ContextMenu

PropTypeDescription
onOpenChange(open: boolean) => voidCallback fired when the menu open state changes.
childrenReact.ReactNodeThe content of the context menu.

ContextMenu.Trigger

PropTypeDescription
disabledbooleanWhen true, prevents the context menu from opening on right-click.
childrenReact.ReactNodeThe element that serves as the right-click target area.

ContextMenu.Content

PropTypeDefaultDescription
align"start" | "center" | "end""start"Alignment of the menu relative to the cursor.
sideOffsetnumber0Distance offset from the cursor position.
childrenReact.ReactNodeThe menu items and groups to render.

ContextMenu.Item

PropTypeDescription
iconReact.ReactNodeAn optional icon displayed before the item text.
shortcutstringA keyboard shortcut hint displayed at the end of the item.
destructivebooleanWhen true, styles the item with a danger appearance.
disabledbooleanWhen true, prevents user interaction with the item.
onSelect() => voidEvent handler called when the user selects the item.
childrenReact.ReactNodeThe label content of the menu item.

ContextMenu.CheckboxItem

PropTypeDescription
checkedbooleanThe controlled checked state of the item.
onCheckedChange(checked: boolean) => voidEvent handler called when the checked state changes.
iconReact.ReactNodeAn optional icon displayed before the item text.
shortcutstringA keyboard shortcut hint displayed at the end of the item.
disabledbooleanWhen true, prevents user interaction with the item.
childrenReact.ReactNodeThe label content of the checkbox item.

ContextMenu.RadioGroup

PropTypeDescription
valuestringThe value of the currently selected radio item.
onValueChange(value: string) => voidEvent handler called when the value changes.
childrenReact.ReactNodeThe radio items to render inside the group.

ContextMenu.RadioItem

PropTypeDescription
valuestringThe unique value that identifies this radio item.
iconReact.ReactNodeAn optional icon displayed before the item text.
shortcutstringA keyboard shortcut hint displayed at the end of the item.
disabledbooleanWhen true, prevents user interaction with the item.
childrenReact.ReactNodeThe label content of the radio item.

ContextMenu.Sub

PropTypeDescription
childrenReact.ReactNodeMust contain a SubTrigger and SubContent.

ContextMenu.SubTrigger

PropTypeDescription
iconReact.ReactNodeAn optional icon displayed before the trigger text.
disabledbooleanWhen true, prevents the submenu from opening.
childrenReact.ReactNodeThe label content of the submenu trigger.

ContextMenu.SubContent

PropTypeDescription
childrenReact.ReactNodeThe menu items to render inside the submenu.

ContextMenu.Separator

No meaningful props.

ContextMenu.Label

No meaningful props.

On this page