Skip to main content
Dropdown menu with items, labels, and dividers. Perfect for action menus, context menus, and navigation dropdowns.

Import

import { Menu } from '@kivora/react';

Usage

import { Menu, Button } from '@kivora/react';

function Example() {
  return (
    <Menu>
      <Menu.Target>
        <Button label="Actions" />
      </Menu.Target>
      <Menu.Dropdown>
        <Menu.Item>Edit</Menu.Item>
        <Menu.Item>Duplicate</Menu.Item>
        <Menu.Divider />
        <Menu.Item color="error">Delete</Menu.Item>
      </Menu.Dropdown>
    </Menu>
  );
}

With Icons

import { Edit, Copy, Trash } from 'lucide-react';

<Menu>
  <Menu.Target>
    <Button label="Options" />
  </Menu.Target>
  <Menu.Dropdown>
    <Menu.Item leftSection={<Edit size={16} />}>Edit</Menu.Item>
    <Menu.Item leftSection={<Copy size={16} />}>Duplicate</Menu.Item>
    <Menu.Divider />
    <Menu.Item leftSection={<Trash size={16} />} color="error">
      Delete
    </Menu.Item>
  </Menu.Dropdown>
</Menu>

With Keyboard Shortcuts

<Menu>
  <Menu.Target>
    <Button label="Edit" />
  </Menu.Target>
  <Menu.Dropdown>
    <Menu.Item rightSection="⌘Z">Undo</Menu.Item>
    <Menu.Item rightSection="⌘⇧Z">Redo</Menu.Item>
    <Menu.Divider />
    <Menu.Item rightSection="⌘X">Cut</Menu.Item>
    <Menu.Item rightSection="⌘C">Copy</Menu.Item>
    <Menu.Item rightSection="⌘V">Paste</Menu.Item>
  </Menu.Dropdown>
</Menu>

With Labels

<Menu>
  <Menu.Target>
    <Button label="File" />
  </Menu.Target>
  <Menu.Dropdown>
    <Menu.Label>File</Menu.Label>
    <Menu.Item>New</Menu.Item>
    <Menu.Item>Open</Menu.Item>
    <Menu.Item>Save</Menu.Item>
    <Menu.Divider />
    <Menu.Label>Recent</Menu.Label>
    <Menu.Item>Project A</Menu.Item>
    <Menu.Item>Project B</Menu.Item>
  </Menu.Dropdown>
</Menu>

Positions

Control where the menu appears:
<Menu position="bottom-start">
  <Menu.Target><Button label="Bottom Start" /></Menu.Target>
  <Menu.Dropdown>
    <Menu.Item>Item</Menu.Item>
  </Menu.Dropdown>
</Menu>

<Menu position="bottom-end">
  <Menu.Target><Button label="Bottom End" /></Menu.Target>
  <Menu.Dropdown>
    <Menu.Item>Item</Menu.Item>
  </Menu.Dropdown>
</Menu>

<Menu position="top-start">
  <Menu.Target><Button label="Top Start" /></Menu.Target>
  <Menu.Dropdown>
    <Menu.Item>Item</Menu.Item>
  </Menu.Dropdown>
</Menu>

Custom Width

<Menu width={300}>
  <Menu.Target>
    <Button label="Wide Menu" />
  </Menu.Target>
  <Menu.Dropdown>
    <Menu.Item>Item with more space</Menu.Item>
  </Menu.Dropdown>
</Menu>

{/* Match trigger width */}
<Menu width="target">
  <Menu.Target>
    <Button label="Matching Width" />
  </Menu.Target>
  <Menu.Dropdown>
    <Menu.Item>Item</Menu.Item>
  </Menu.Dropdown>
</Menu>

Controlled

function ControlledMenu() {
  const [opened, setOpened] = useState(false);

  return (
    <Menu
      opened={opened}
      onOpen={() => setOpened(true)}
      onClose={() => setOpened(false)}
    >
      <Menu.Target>
        <Button label="Controlled" />
      </Menu.Target>
      <Menu.Dropdown>
        <Menu.Item onClick={() => console.log('Clicked')}>Action</Menu.Item>
      </Menu.Dropdown>
    </Menu>
  );
}

Disable Auto Close

Prevent menu from closing when items are clicked:
<Menu closeOnItemClick={false}>
  <Menu.Target>
    <Button label="Filters" />
  </Menu.Target>
  <Menu.Dropdown>
    <Menu.Item>
      <label className="flex items-center gap-2">
        <input type="checkbox" />
        Option 1
      </label>
    </Menu.Item>
    <Menu.Item>
      <label className="flex items-center gap-2">
        <input type="checkbox" />
        Option 2
      </label>
    </Menu.Item>
  </Menu.Dropdown>
</Menu>

Context Menu

import { MoreVertical, Eye, Download, Link, Trash } from 'lucide-react';

function ContextMenu() {
  return (
    <Menu position="bottom-end">
      <Menu.Target>
        <button className="p-2 rounded hover:bg-accent">
          <MoreVertical size={16} />
        </button>
      </Menu.Target>
      <Menu.Dropdown>
        <Menu.Item leftSection={<Eye size={16} />}>View details</Menu.Item>
        <Menu.Item leftSection={<Download size={16} />}>Download</Menu.Item>
        <Menu.Item leftSection={<Link size={16} />}>Copy link</Menu.Item>
        <Menu.Divider />
        <Menu.Item leftSection={<Trash size={16} />} color="error">
          Delete
        </Menu.Item>
      </Menu.Dropdown>
    </Menu>
  );
}

Nested Sections

<Menu>
  <Menu.Target>
    <Button label="Settings" />
  </Menu.Target>
  <Menu.Dropdown>
    <Menu.Label>Account</Menu.Label>
    <Menu.Item>Profile</Menu.Item>
    <Menu.Item>Preferences</Menu.Item>
    <Menu.Divider label="Workspace" />
    <Menu.Item>Members</Menu.Item>
    <Menu.Item>Billing</Menu.Item>
    <Menu.Divider />
    <Menu.Item>Sign out</Menu.Item>
  </Menu.Dropdown>
</Menu>

Disabled Items

<Menu>
  <Menu.Target>
    <Button label="Actions" />
  </Menu.Target>
  <Menu.Dropdown>
    <Menu.Item>Active item</Menu.Item>
    <Menu.Item disabled>Disabled item</Menu.Item>
    <Menu.Item>Another active item</Menu.Item>
  </Menu.Dropdown>
</Menu>

Props

children
ReactNode
required
Must include Menu.Target and Menu.Dropdown components
position
'bottom-start' | 'bottom-end' | 'top-start' | 'top-end'
default:"bottom-start"
Where the menu appears relative to the trigger
width
number | 'target'
default:"220"
Width in pixels or ‘target’ to match trigger width
closeOnItemClick
boolean
default:"true"
Whether clicking menu items closes the menu
opened
boolean
Controlled open state
onOpen
() => void
Callback fired when menu opens
onClose
() => void
Callback fired when menu closes
children
ReactNode
required
Item label or content
leftSection
ReactNode
Content shown on the left (typically an icon)
rightSection
ReactNode
Content shown on the right (typically a keyboard shortcut)
color
'default' | 'error'
default:"default"
Color variant for destructive actions
disabled
boolean
Whether the item is disabled
onClick
(e: React.MouseEvent) => void
Click handler
label
string
Optional label for the divider
children
ReactNode
required
Label text

Accessibility

  • Uses role="menu" and role="menuitem"
  • Keyboard navigation support
  • Focus management
  • Click outside to close
  • Disabled state support
  • Proper ARIA labels

Features

  • Compound component pattern
  • Click to toggle open/close
  • Configurable positioning
  • Custom width options
  • Auto-close on item click (configurable)
  • Controlled and uncontrolled modes
  • Icons and keyboard shortcuts
  • Labels and dividers
  • Destructive action styling
  • Smooth animations

Build docs developers (and LLMs) love