# Dropdown **Category**: react **URL**: https://www.heroui.com/docs/react/components/dropdown **Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/react/components/(collections)/dropdown.mdx > A dropdown displays a list of actions or options that a user can choose *** ## Import ```tsx import { Dropdown } from '@heroui/react'; ``` ### Usage ```tsx "use client"; import {Button, Dropdown, Label} from "@heroui/react"; export function Default() { return ( console.log(`Selected: ${key}`)}> ); } ``` ### Anatomy Import the Dropdown component and access all parts using dot notation. ```tsx import { Dropdown, Button, Label, Description, Header, Kbd, Separator } from '@heroui/react'; export default () => (
Select a fruit
); } ``` ### Single With Custom Indicator ```tsx "use client"; import type {Selection} from "@heroui/react"; import {Button, Dropdown, Header, Label} from "@heroui/react"; import {useState} from "react"; export function SingleWithCustomIndicator() { const [selected, setSelected] = useState(new Set(["apple"])); const CustomCheckmarkIcon = ( ); return (
Select a fruit
{({isSelected}) => (isSelected ? CustomCheckmarkIcon : null)} {({isSelected}) => (isSelected ? CustomCheckmarkIcon : null)} {({isSelected}) => (isSelected ? CustomCheckmarkIcon : null)}
{({isSelected}) => (isSelected ? CustomCheckmarkIcon : null)} {({isSelected}) => (isSelected ? CustomCheckmarkIcon : null)}
); } ``` ### With Multiple Selection ```tsx "use client"; import type {Selection} from "@heroui/react"; import {Button, Dropdown, Header, Label} from "@heroui/react"; import {useState} from "react"; export function WithMultipleSelection() { const [selected, setSelected] = useState(new Set(["apple"])); return (
Select a fruit
); } ``` ### With Section Level Selection ```tsx "use client"; import type {Selection} from "@heroui/react"; import {Button, Dropdown, Header, Kbd, Label, Separator} from "@heroui/react"; import {useState} from "react"; export function WithSectionLevelSelection() { const [textStyles, setTextStyles] = useState(new Set(["bold", "italic"])); const [textAlignment, setTextAlignment] = useState(new Set(["left"])); return (
Actions
X C U
Text Style
B I U
Text Alignment
A H D
); } ``` ### With Keyboard Shortcuts ```tsx "use client"; import {Button, Dropdown, Kbd, Label} from "@heroui/react"; export function WithKeyboardShortcuts() { return ( console.log(`Selected: ${key}`)}> N O S D ); } ``` ### With Icons ```tsx "use client"; import {FloppyDisk, FolderOpen, SquarePlus, TrashBin} from "@gravity-ui/icons"; import {Button, Dropdown, Kbd, Label} from "@heroui/react"; export function WithIcons() { return ( console.log(`Selected: ${key}`)}> N O S D ); } ``` ### Long Press Trigger ```tsx import {Button, Dropdown, Label} from "@heroui/react"; export function LongPressTrigger() { return ( ); } ``` ### With Descriptions ```tsx "use client"; import {FloppyDisk, FolderOpen, SquarePlus, TrashBin} from "@gravity-ui/icons"; import {Button, Description, Dropdown, Kbd, Label} from "@heroui/react"; export function WithDescriptions() { return ( console.log(`Selected: ${key}`)}>
Create a new file
N
Open an existing file
O
Save the current file
S
Move to trash
D
); } ``` ### With Sections ```tsx "use client"; import {EllipsisVertical, Pencil, SquarePlus, TrashBin} from "@gravity-ui/icons"; import {Button, Description, Dropdown, Header, Kbd, Label, Separator} from "@heroui/react"; export function WithSections() { return ( console.log(`Selected: ${key}`)}>
Actions
Create a new file
N
Make changes
E
Danger zone
Move to trash
D
); } ``` ### With Disabled Items ```tsx "use client"; import {Bars, Pencil, SquarePlus, TrashBin} from "@gravity-ui/icons"; import {Button, Description, Dropdown, Header, Kbd, Label, Separator} from "@heroui/react"; export function WithDisabledItems() { return ( console.log(`Selected: ${key}`)} >
Actions
Create a new file
N
Make changes
E
Danger zone
Move to trash
D
); } ``` ### With Submenus ```tsx "use client"; import {Button, Dropdown, Label} from "@heroui/react"; export function WithSubmenus() { return ( console.log(`Selected: ${key}`)}> ); } ``` ### With Custom Submenu Indicator ```tsx "use client"; import {ArrowRight} from "@gravity-ui/icons"; import {Button, Dropdown, Label} from "@heroui/react"; export function WithCustomSubmenuIndicator() { return ( console.log(`Selected: ${key}`)}> ); } ``` ### Controlled ```tsx "use client"; import type {Selection} from "@heroui/react"; import {Button, Dropdown, Label} from "@heroui/react"; import {useState} from "react"; export function Controlled() { const [selected, setSelected] = useState(new Set(["bold"])); const selectedItems = Array.from(selected); return (

Selected: {selectedItems.length > 0 ? selectedItems.join(", ") : "None"}

); } ``` ### Controlled Open State ```tsx "use client"; import {Button, Dropdown, Label} from "@heroui/react"; import {useState} from "react"; export function ControlledOpenState() { const [open, setOpen] = useState(false); return (

Dropdown is: {open ? "open" : "closed"}

); } ``` ### Custom Trigger ```tsx import {ArrowRightFromSquare, Gear, Persons} from "@gravity-ui/icons"; import {Avatar, Dropdown, Label} from "@heroui/react"; export function CustomTrigger() { return ( JD
JD

Jane Doe

jane@example.com

); } ``` ## Related Components - **Button**: Allows a user to perform an action - **Popover**: Displays content in context with a trigger - **Separator**: Visual divider between content ## Styling ### Passing Tailwind CSS classes ```tsx import { Dropdown, Button } from '@heroui/react'; function CustomDropdown() { return ( Item 1 ); } ``` ### Customizing the component classes To customize the Dropdown component classes, you can use the `@layer components` directive.
[Learn more](https://tailwindcss.com/docs/adding-custom-styles#adding-component-classes). ```css @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; } } ``` HeroUI follows the [BEM](https://getbem.com/) 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](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/dropdown.css)): #### 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](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/menu.css)) - `[data-slot="separator"]` - Separator elements within the menu #### MenuItem Classes - `.menu-item` - Base menu item container ([menu-item.css](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/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](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/menu-section.css)) ### Interactive States The component supports both CSS pseudo-classes and data attributes for flexibility: - **Hover**: `:hover` or `[data-hovered="true"]` on trigger and items - **Focus**: `:focus-visible` or `[data-focus-visible="true"]` on trigger and items - **Disabled**: `:disabled` or `[data-disabled="true"]` on trigger and items - **Pressed**: `:active` or `[data-pressed="true"]` on trigger and items - **Selected**: `[data-selected="true"]` or `[aria-selected="true"]` on items ## API Reference ### Dropdown Props | 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 Props | Prop | Type | Default | Description | |------|------|---------|-------------| | `className` | `string` | - | Additional CSS classes | | `children` | `ReactNode \| RenderFunction` | - | Trigger content or render function | All [Button](https://react-spectrum.adobe.com/react-aria/Button.html) props are also supported when using a Button as the trigger. ### Dropdown.Popover Props | 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](https://react-spectrum.adobe.com/react-aria/Popover.html) props are also supported. ### Dropdown.Menu Props | Prop | Type | Default | Description | |------|------|---------|-------------| | `selectionMode` | `"single" \| "multiple" \| "none"` | `"none"` | Whether single or multiple selection is enabled | | `selectedKeys` | `Iterable` | - | The currently selected keys (controlled) | | `defaultSelectedKeys` | `Iterable` | - | The initial selected keys (uncontrolled) | | `onSelectionChange` | `(keys: Selection) => void` | - | Handler called when the selection changes | | `disabledKeys` | `Iterable` | - | 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](https://react-spectrum.adobe.com/react-aria/Menu.html#menu) props are also supported. ### Dropdown.Section Props | Prop | Type | Default | Description | |------|------|---------|-------------| | `selectionMode` | `"single" \| "multiple"` | - | Selection mode for items within this section | | `selectedKeys` | `Iterable` | - | The currently selected keys (controlled) | | `defaultSelectedKeys` | `Iterable` | - | The initial selected keys (uncontrolled) | | `onSelectionChange` | `(keys: Selection) => void` | - | Handler called when the selection changes | | `disabledKeys` | `Iterable` | - | Keys of disabled items | | `className` | `string` | - | Additional CSS classes | | `children` | `ReactNode` | - | Section content | All [MenuSection](https://react-spectrum.adobe.com/react-aria/Menu.html#menusection) props are also supported. ### Dropdown.Item Props | 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](https://react-spectrum.adobe.com/react-aria/Menu.html#menuitem) props are also supported. ### Dropdown.ItemIndicator Props | 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 Props | Prop | Type | Default | Description | |------|------|---------|-------------| | `className` | `string` | - | Additional CSS classes | | `children` | `ReactNode` | - | Custom indicator content | ### Dropdown.SubmenuTrigger Props | Prop | Type | Default | Description | |------|------|---------|-------------| | `className` | `string` | - | Additional CSS classes | | `children` | `ReactNode` | - | Submenu trigger content | All [SubmenuTrigger](https://react-spectrum.adobe.com/react-aria/Menu.html#submenutrigger) props are also supported. ### RenderProps 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 ```tsx import { Dropdown, Button, Label } from '@heroui/react'; alert(`Selected: ${key}`)}> ``` ### With Sections ```tsx import { Dropdown, Button, Label, Header, Separator } from '@heroui/react'; alert(`Selected: ${key}`)}>
Actions
Danger zone
``` ### Controlled Selection ```tsx import type { Selection } from '@heroui/react'; import { Dropdown, Button, Label } from '@heroui/react'; import { useState } from 'react'; function ControlledDropdown() { const [selected, setSelected] = useState(new Set(['bold'])); return ( ); } ``` ### With Submenus ```tsx import { Dropdown, Button, Label } from '@heroui/react'; alert(`Selected: ${key}`)}> ``` ## 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](https://react-spectrum.adobe.com/react-aria/Menu.html#menu).