Dropdown
A dropdown displays a list of actions or options that a user can choose
Usage
import { Dropdown } from '@heroui/react';Anatomy
import { Dropdown, Button, Label, Description, Header, Kbd, Separator } from '@heroui/react';
export default () => (
<Dropdown>
<Dropdown.Trigger>
<Button />
</Dropdown.Trigger>
<Dropdown.Popover>
<Dropdown.Menu>
<Dropdown.Item>
<Label />
<Description />
<Kbd slot="keyboard" />
<Dropdown.ItemIndicator />
</Dropdown.Item>
<Separator />
<Dropdown.Section>
<Header />
<Dropdown.Item />
</Dropdown.Section>
<Dropdown.SubmenuTrigger>
<Dropdown.Item>
<Label />
<Dropdown.SubmenuIndicator />
</Dropdown.Item>
<Dropdown.Popover>
<Dropdown.Menu>
<Dropdown.Item />
</Dropdown.Menu>
</Dropdown.Popover>
</Dropdown.SubmenuTrigger>
</Dropdown.Menu>
</Dropdown.Popover>
</Dropdown>
)Examples
With Icons
With Descriptions
With Disabled Items
With Sections
With Multiple Selection
Controlled
Controlled Open State
With Single Selection
Single With Custom Indicator
With Section Level Selection
With Keyboard Shortcuts
With Submenus
With Custom Submenu Indicator
Custom Trigger
Long Press Trigger
Customization
Tailwind CSS
Global CSS
To customize the Dropdown component classes, you can use the @layer components directive.
Learn more.
@layer components {
.dropdown {
@apply flex flex-col gap-1;
}
.dropdown__trigger {
@apply outline-none;
}
.dropdown__popover {
@apply rounded-lg border border-border bg-overlay p-2;
}
.dropdown__menu {
@apply flex flex-col gap-1;
}
}Styling Reference
HeroUI follows the BEM methodology to ensure component variants and states are reusable and easy to customize.
CSS Classes
The Dropdown component uses these CSS classes (View source styles):
Base Classes
.dropdown- Base dropdown container.dropdown__trigger- The button or element that triggers the dropdown.dropdown__popover- The popover container.dropdown__menu- The menu container inside the popover
State Classes
.dropdown__trigger[data-focus-visible="true"]- Focused trigger state.dropdown__trigger[data-disabled="true"]- Disabled trigger state.dropdown__trigger[data-pressed="true"]- Pressed trigger state.dropdown__popover[data-entering]- Entering animation state.dropdown__popover[data-exiting]- Exiting animation state.dropdown__menu[data-selection-mode="single"]- Single selection mode.dropdown__menu[data-selection-mode="multiple"]- Multiple selection mode
Menu Component Classes
The Dropdown component uses Menu, MenuItem, and MenuSection as base components. These classes are also available for customization:
Menu Classes
.menu- Base menu container (menu.css)[data-slot="separator"]- Separator elements within the menu
MenuItem Classes
.menu-item- Base menu item container (menu-item.css).menu-item__indicator- Selection indicator (checkmark or dot)[data-slot="menu-item-indicator--checkmark"]- Checkmark indicator SVG[data-slot="menu-item-indicator--dot"]- Dot indicator SVG
.menu-item__indicator--submenu- Submenu indicator (chevron).menu-item--default- Default variant styling.menu-item--danger- Danger variant styling
MenuItem State Classes
.menu-item[data-focus-visible="true"]- Focused item state (keyboard focus).menu-item[data-focus="true"]- Focused item state.menu-item[data-pressed]- Pressed item state.menu-item[data-hovered]- Hovered item state.menu-item[data-selected="true"]- Selected item state.menu-item[data-disabled]- Disabled item state.menu-item[data-has-submenu="true"]- Item with submenu.menu-item[data-selection-mode="single"]- Single selection mode.menu-item[data-selection-mode="multiple"]- Multiple selection mode.menu-item[aria-checked="true"]- Checked item (ARIA).menu-item[aria-selected="true"]- Selected item (ARIA)
MenuSection Classes
.menu-section- Base menu section container (menu-section.css)
Interactive States
The component supports both CSS pseudo-classes and data attributes for flexibility:
- Hover:
:hoveror[data-hovered="true"]on trigger and items - Focus:
:focus-visibleor[data-focus-visible="true"]on trigger and items - Disabled:
:disabledor[data-disabled="true"]on trigger and items - Pressed:
:activeor[data-pressed="true"]on trigger and items - Selected:
[data-selected="true"]or[aria-selected="true"]on items
API Reference
Dropdown
| Prop | Type | Default | Description |
|---|---|---|---|
isOpen | boolean | - | Sets the open state of the menu (controlled) |
defaultOpen | boolean | - | Sets the default open state of the menu (uncontrolled) |
onOpenChange | (isOpen: boolean) => void | - | Handler called when the open state changes |
trigger | "press" | "longPress" | "press" | The type of interaction that triggers the menu |
className | string | - | Additional CSS classes |
children | ReactNode | - | Dropdown content |
Dropdown.Trigger
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | - | Additional CSS classes |
children | ReactNode | RenderFunction | - | Trigger content or render function |
All Button props are also supported when using a Button as the trigger.
Dropdown.Popover
| Prop | Type | Default | Description |
|---|---|---|---|
placement | "bottom" | "bottom left" | "bottom right" | "bottom start" | "bottom end" | "top" | "top left" | "top right" | "top start" | "top end" | "left" | "left top" | "left bottom" | "start" | "start top" | "start bottom" | "right" | "right top" | "right bottom" | "end" | "end top" | "end bottom" | "bottom" | Placement of the popover relative to the trigger |
className | string | - | Additional CSS classes |
children | ReactNode | - | Content children |
All Popover props are also supported.
Dropdown.Menu
| Prop | Type | Default | Description |
|---|---|---|---|
selectionMode | "single" | "multiple" | "none" | "none" | Whether single or multiple selection is enabled |
selectedKeys | Iterable<Key> | - | The currently selected keys (controlled) |
defaultSelectedKeys | Iterable<Key> | - | The initial selected keys (uncontrolled) |
onSelectionChange | (keys: Selection) => void | - | Handler called when the selection changes |
disabledKeys | Iterable<Key> | - | Keys of disabled items |
onAction | (key: Key) => void | - | Handler called when an item is activated |
className | string | - | Additional CSS classes |
children | ReactNode | - | Menu content |
All Menu props are also supported.
Dropdown.Section
| Prop | Type | Default | Description |
|---|---|---|---|
selectionMode | "single" | "multiple" | - | Selection mode for items within this section |
selectedKeys | Iterable<Key> | - | The currently selected keys (controlled) |
defaultSelectedKeys | Iterable<Key> | - | The initial selected keys (uncontrolled) |
onSelectionChange | (keys: Selection) => void | - | Handler called when the selection changes |
disabledKeys | Iterable<Key> | - | Keys of disabled items |
className | string | - | Additional CSS classes |
children | ReactNode | - | Section content |
All MenuSection props are also supported.
Dropdown.Item
| Prop | Type | Default | Description |
|---|---|---|---|
id | Key | - | Unique identifier for the item |
textValue | string | - | Text content of the item for typeahead |
variant | "default" | "danger" | "default" | Visual variant of the item |
className | string | - | Additional CSS classes |
children | ReactNode | RenderFunction | - | Item content or render function |
All MenuItem props are also supported.
Dropdown.ItemIndicator
| Prop | Type | Default | Description |
|---|---|---|---|
type | "checkmark" | "dot" | "checkmark" | Type of indicator to display |
className | string | - | Additional CSS classes |
children | ReactNode | RenderFunction | - | Custom indicator content or render function |
When using a render function, these values are provided:
| Prop | Type | Description |
|---|---|---|
isSelected | boolean | Whether the item is selected |
isIndeterminate | boolean | Whether the item is in an indeterminate state |
Dropdown.SubmenuIndicator
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | - | Additional CSS classes |
children | ReactNode | - | Custom indicator content |
Dropdown.SubmenuTrigger
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | - | Additional CSS classes |
children | ReactNode | - | Submenu trigger content |
All SubmenuTrigger props are also supported.
Render Props
When using render functions with Dropdown.Item, these values are provided:
| Prop | Type | Description |
|---|---|---|
isSelected | boolean | Whether the item is selected |
isFocused | boolean | Whether the item is focused |
isDisabled | boolean | Whether the item is disabled |
isPressed | boolean | Whether the item is being pressed |
Examples
Basic Usage
import { Dropdown, Button, Label } from '@heroui/react';
<Dropdown>
<Button aria-label="Menu" variant="secondary">
Actions
</Button>
<Dropdown.Popover>
<Dropdown.Menu onAction={(key) => alert(`Selected: ${key}`)}>
<Dropdown.Item id="new-file" textValue="New file">
<Label>New file</Label>
</Dropdown.Item>
<Dropdown.Item id="open-file" textValue="Open file">
<Label>Open file</Label>
</Dropdown.Item>
<Dropdown.Item id="delete-file" textValue="Delete file" variant="danger">
<Label>Delete file</Label>
</Dropdown.Item>
</Dropdown.Menu>
</Dropdown.Popover>
</Dropdown>With Sections
import { Dropdown, Button, Label, Header, Separator } from '@heroui/react';
<Dropdown>
<Button aria-label="Menu" variant="secondary">
Actions
</Button>
<Dropdown.Popover>
<Dropdown.Menu onAction={(key) => alert(`Selected: ${key}`)}>
<Dropdown.Section>
<Header>Actions</Header>
<Dropdown.Item id="new-file" textValue="New file">
<Label>New file</Label>
</Dropdown.Item>
<Dropdown.Item id="edit-file" textValue="Edit file">
<Label>Edit file</Label>
</Dropdown.Item>
</Dropdown.Section>
<Separator />
<Dropdown.Section>
<Header>Danger zone</Header>
<Dropdown.Item id="delete-file" textValue="Delete file" variant="danger">
<Label>Delete file</Label>
</Dropdown.Item>
</Dropdown.Section>
</Dropdown.Menu>
</Dropdown.Popover>
</Dropdown>Controlled Selection
import type { Selection } from '@heroui/react';
import { Dropdown, Button, Label } from '@heroui/react';
import { useState } from 'react';
function ControlledDropdown() {
const [selected, setSelected] = useState<Selection>(new Set(['bold']));
return (
<Dropdown>
<Button aria-label="Menu" variant="secondary">
Actions
</Button>
<Dropdown.Popover>
<Dropdown.Menu
selectedKeys={selected}
selectionMode="multiple"
onSelectionChange={setSelected}
>
<Dropdown.Item id="bold" textValue="Bold">
<Label>Bold</Label>
<Dropdown.ItemIndicator />
</Dropdown.Item>
<Dropdown.Item id="italic" textValue="Italic">
<Label>Italic</Label>
<Dropdown.ItemIndicator />
</Dropdown.Item>
</Dropdown.Menu>
</Dropdown.Popover>
</Dropdown>
);
}With Submenus
import { Dropdown, Button, Label } from '@heroui/react';
<Dropdown>
<Button aria-label="Menu" variant="secondary">
Share
</Button>
<Dropdown.Popover>
<Dropdown.Menu onAction={(key) => alert(`Selected: ${key}`)}>
<Dropdown.Item id="copy-link" textValue="Copy Link">
<Label>Copy Link</Label>
</Dropdown.Item>
<Dropdown.SubmenuTrigger>
<Dropdown.Item id="share" textValue="Share">
<Label>Other</Label>
<Dropdown.SubmenuIndicator />
</Dropdown.Item>
<Dropdown.Popover>
<Dropdown.Menu>
<Dropdown.Item id="whatsapp" textValue="WhatsApp">
<Label>WhatsApp</Label>
</Dropdown.Item>
<Dropdown.Item id="telegram" textValue="Telegram">
<Label>Telegram</Label>
</Dropdown.Item>
</Dropdown.Menu>
</Dropdown.Popover>
</Dropdown.SubmenuTrigger>
</Dropdown.Menu>
</Dropdown.Popover>
</Dropdown>Accessibility
The Dropdown component implements the ARIA menu pattern and provides:
- Full keyboard navigation support (arrow keys, home/end, typeahead)
- Screen reader announcements for actions and selection changes
- Proper focus management
- Support for disabled states
- Long press interaction support
- Submenu navigation
For more information, see the React Aria Menu documentation.





