Skip to content

DropdownMenu

Desktop-style popup menu with click trigger and context menu support.

Basic Usage

Wrap the trigger element with DropdownMenu and define menu items with DropdownMenu.Item.

tsx
import { DropdownMenu, Button } from '@airo-ui/react'

function Demo() {
  return (
    <DropdownMenu
      triggerContent={<Button>Actions</Button>}
      placement="bottom-start"
    >
      <DropdownMenu.Item label="New File" />
      <DropdownMenu.Item label="Open File" />
      <DropdownMenu.Divider />
      <DropdownMenu.Item label="Save" accelerator="Cmd+S" />
      <DropdownMenu.Item label="Save As" disabled />
    </DropdownMenu>
  )
}

Danger Action

Set danger to mark a dangerous action.

tsx
<DropdownMenu triggerContent={<Button>More</Button>}>
  <DropdownMenu.Item label="Edit" />
  <DropdownMenu.Divider />
  <DropdownMenu.Item label="Delete" danger />
</DropdownMenu>

Context Menu

Set trigger="contextmenu" for right-click menu.

tsx
<DropdownMenu
  trigger="contextmenu"
  triggerContent={
    <div style={{
      padding: 24,
      border: '1px dashed var(--color-neutral-300)',
      borderRadius: 'var(--radius-md)',
      textAlign: 'center',
      color: 'var(--color-neutral-500)',
      fontSize: 13,
    }}>
      Right-click here
    </div>
  }
>
  <DropdownMenu.Item label="Copy" accelerator="Cmd+C" />
  <DropdownMenu.Item label="Paste" accelerator="Cmd+V" />
  <DropdownMenu.Divider />
  <DropdownMenu.Item label="Select All" accelerator="Cmd+A" />
</DropdownMenu>

Groups

Use DropdownMenu.Group to group menu items.

tsx
<DropdownMenu triggerContent={<Button>Group Menu</Button>}>
  <DropdownMenu.Group label="Edit">
    <DropdownMenu.Item label="Undo" accelerator="Cmd+Z" />
    <DropdownMenu.Item label="Redo" accelerator="Cmd+Shift+Z" />
  </DropdownMenu.Group>
  <DropdownMenu.Divider />
  <DropdownMenu.Group label="View">
    <DropdownMenu.Item label="Zoom" />
    <DropdownMenu.Item label="Fullscreen" accelerator="F11" />
  </DropdownMenu.Group>
</DropdownMenu>

Controlled Open State

tsx
import { useState } from 'react'

function Demo() {
  const [open, setOpen] = useState(false)

  return (
    <DropdownMenu
      open={open}
      onOpenChange={setOpen}
      triggerContent={<Button>Controlled</Button>}
    >
      <DropdownMenu.Item label="Item 1" />
      <DropdownMenu.Item label="Item 2" />
    </DropdownMenu>
  )
}

API

NameTypeDefaultDescription
openboolean--Controlled open state
onOpenChange(open: boolean) => void--Open state change handler
trigger'click' | 'contextmenu' | 'hover''click'Trigger method
placement'bottom-start' | 'bottom' | 'bottom-end' | 'top-start' | 'top' | 'top-end''bottom-start'Popup position
disabledbooleanfalseDisabled
autoClosebooleantrueAuto-close on item click
triggerContentReact.ReactNode--Trigger element
childrenReact.ReactNode--Menu items
onOpen() => void--Opened callback
onClose() => void--Closed callback
NameTypeDefaultDescription
labelstring--Menu item text
disabledbooleanfalseDisabled
dangerbooleanfalseDanger mode (red text)
iconstring--Icon class name (RemixIcon)
acceleratorstring--Keyboard shortcut text
onClick(e: MouseEvent<HTMLButtonElement>) => void--Click handler
NameTypeDefaultDescription
labelstring--Group label
childrenReact.ReactNode--Menu items

Interaction

  • Auto-close on outside click
  • Auto-close on item select (autoClose)
  • Disabled state prevents interaction
  • Danger operations highlighted in red
  • Context menu positions at mouse location
  • Fade + translate open animation

MIT License