Skip to content

ContextMenu

Right-click context menu with nested submenus and icons.

import { ContextMenu } from 'asterui'

Basic Context Menu

Right-click on the element to show the menu.

Right-click here
import { ContextMenu, notification } from 'asterui'

function App() {
  return (
      <ContextMenu onSelect={(key) => notification.info({ message: `Selected: ${key}` })}>
        <div className="p-8 bg-base-200 rounded-lg text-center cursor-context-menu">
          Right-click here
        </div>
        <ContextMenu.Item key="copy">Copy</ContextMenu.Item>
        <ContextMenu.Item key="paste">Paste</ContextMenu.Item>
        <ContextMenu.Item key="cut">Cut</ContextMenu.Item>
      </ContextMenu>
    )
}

export default App

Data-Driven Pattern

Use items prop for data-driven menus.

Right-click here
import { ContextMenu, notification } from 'asterui'

function App() {
  const items = [
    { key: 'copy', label: 'Copy' },
    { key: 'paste', label: 'Paste' },
    { key: 'cut', label: 'Cut' },
  ]
  
  return (
      <ContextMenu items={items} onSelect={(key) => notification.info({ message: `Selected: ${key}` })}>
        <div className="p-8 bg-base-200 rounded-lg text-center cursor-context-menu">
          Right-click here
        </div>
      </ContextMenu>
    )
}

export default App

With Icons

Menu items with icons.

Right-click for options
import { ContextMenu, notification } from 'asterui'

function App() {
  const items = [
    { key: 'edit', label: 'Edit', icon: <span>✏️</span> },
    { key: 'duplicate', label: 'Duplicate', icon: <span>📋</span> },
    { key: 'delete', label: 'Delete', icon: <span>🗑️</span>, danger: true },
  ]
  
  return (
      <ContextMenu items={items} onSelect={(key) => notification.info({ message: `Selected: ${key}` })}>
        <div className="p-8 bg-base-200 rounded-lg text-center cursor-context-menu">
          Right-click for options
        </div>
      </ContextMenu>
    )
}

export default App

With Dividers

Separate menu sections with dividers.

Right-click for menu with sections
import { ContextMenu, notification } from 'asterui'

function App() {
  const items = [
    { key: 'undo', label: 'Undo' },
    { key: 'redo', label: 'Redo' },
    { key: 'divider1', divider: true },
    { key: 'cut', label: 'Cut' },
    { key: 'copy', label: 'Copy' },
    { key: 'paste', label: 'Paste' },
    { key: 'divider2', divider: true },
    { key: 'select-all', label: 'Select All' },
  ]
  
  return (
      <ContextMenu items={items} onSelect={(key) => notification.info({ message: `Selected: ${key}` })}>
        <div className="p-8 bg-base-200 rounded-lg text-center cursor-context-menu">
          Right-click for menu with sections
        </div>
      </ContextMenu>
    )
}

export default App

Nested Submenu

Menu items with nested submenus.

Right-click for nested menu
import { ContextMenu, notification } from 'asterui'

function App() {
  const items = [
    { key: 'new', label: 'New', children: [
      { key: 'new-file', label: 'File' },
      { key: 'new-folder', label: 'Folder' },
      { key: 'new-project', label: 'Project' },
    ]},
    { key: 'open', label: 'Open' },
    { key: 'save', label: 'Save' },
    { key: 'divider', divider: true },
    { key: 'export', label: 'Export', children: [
      { key: 'export-pdf', label: 'PDF' },
      { key: 'export-png', label: 'PNG' },
      { key: 'export-svg', label: 'SVG' },
    ]},
  ]
  
  return (
      <ContextMenu items={items} onSelect={(key) => notification.info({ message: `Selected: ${key}` })}>
        <div className="p-8 bg-base-200 rounded-lg text-center cursor-context-menu">
          Right-click for nested menu
        </div>
      </ContextMenu>
    )
}

export default App

Disabled Items

Some menu items can be disabled.

Right-click (some items disabled)
import { ContextMenu, notification } from 'asterui'

function App() {
  const items = [
    { key: 'copy', label: 'Copy' },
    { key: 'paste', label: 'Paste', disabled: true },
    { key: 'cut', label: 'Cut' },
    { key: 'delete', label: 'Delete', danger: true, disabled: true },
  ]
  
  return (
      <ContextMenu items={items} onSelect={(key) => notification.info({ message: `Selected: ${key}` })}>
        <div className="p-8 bg-base-200 rounded-lg text-center cursor-context-menu">
          Right-click (some items disabled)
        </div>
      </ContextMenu>
    )
}

export default App
PropertyDescriptionTypeDefault
childrenElement that triggers the context menu on right-clickReact.ReactNode-
itemsMenu itemsContextMenuItem[]-
onSelectCallback when an item is selected(key: string) => void-
disabledWhether the context menu is disabledbooleanfalse
classNameAdditional CSS classes for the menustring-
data-testidTest ID for testingstring-
PropertyDescriptionTypeDefault
keyUnique identifier for the itemstring-
labelDisplay labelReact.ReactNode-
iconIcon elementReact.ReactNode-
disabledDisabled statebooleanfalse
dangerShow as danger/destructive actionbooleanfalse
dividerRender as a dividerbooleanfalse
childrenSubmenu itemsContextMenuItem[]-
data-testidTest ID for testingstring-
PropertyDescriptionTypeDefault
keyUnique key for the item (React key prop)string-
childrenItem contentReact.ReactNode-
iconIcon to display before labelReact.ReactNode-
disabledWhether the item is disabledbooleanfalse
dangerShow as danger/destructive actionbooleanfalse
data-testidTest ID for testingstring-
PropertyDescriptionTypeDefault
keyUnique key for the submenu (React key prop)string-
labelSubmenu labelReact.ReactNode-
iconIcon to display before labelReact.ReactNode-
disabledWhether the submenu is disabledbooleanfalse
childrenSubmenu itemsReact.ReactNode-
data-testidTest ID for testingstring-
  • Menu closes on Escape key press
  • Menu closes when clicking outside
  • Menu items are keyboard navigable
  • Disabled items are properly announced