HeroUI

Dropdown

A dropdown displays a list of actions or options that a user can choose

Import

import { Dropdown } from '@heroui/react';

Usage

"use client";

import {Button, Dropdown, Label} from "@heroui/react";

export function Default() {

Anatomy

Import the Dropdown component and access all parts using dot notation.

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>
)

With Single Selection

"use client";

import type {Selection} from "@heroui/react";

import {Button, Dropdown, Header, Label} from "@heroui/react";

Single With Custom Indicator

"use client";

import type {Selection} from "@heroui/react";

import {Button, Dropdown, Header, Label} from "@heroui/react";

With Multiple Selection

"use client";

import type {Selection} from "@heroui/react";

import {Button, Dropdown, Header, Label} from "@heroui/react";

With Section Level Selection

"use client";

import type {Selection} from "@heroui/react";

import {Button, Dropdown, Header, Kbd, Label, Separator} from "@heroui/react";

With Keyboard Shortcuts

"use client";

import {Button, Dropdown, Kbd, Label} from "@heroui/react";

export function WithKeyboardShortcuts() {

With Icons

"use client";

import {FloppyDisk, FolderOpen, SquarePlus, TrashBin} from "@gravity-ui/icons";
import {Button, Dropdown, Kbd, Label} from "@heroui/react";

Long Press Trigger

import {Button, Dropdown, Label} from "@heroui/react";

export function LongPressTrigger() {
  return (
    <Dropdown trigger="longPress">

With Descriptions

"use client";

import {FloppyDisk, FolderOpen, SquarePlus, TrashBin} from "@gravity-ui/icons";
import {Button, Description, Dropdown, Kbd, Label} from "@heroui/react";

With Sections

"use client";

import {EllipsisVertical, Pencil, SquarePlus, TrashBin} from "@gravity-ui/icons";
import {Description, Dropdown, Header, Kbd, Label, Separator} from "@heroui/react";

With Disabled Items

"use client";

import {Bars, Pencil, SquarePlus, TrashBin} from "@gravity-ui/icons";
import {Button, Description, Dropdown, Header, Kbd, Label, Separator} from "@heroui/react";

With Submenus

"use client";

import {Button, Dropdown, Label} from "@heroui/react";

export function WithSubmenus() {

With Custom Submenu Indicator

"use client";

import {ArrowRight} from "@gravity-ui/icons";
import {Button, Dropdown, Label} from "@heroui/react";

Controlled

Selected: bold

"use client";

import type {Selection} from "@heroui/react";

import {Button, Dropdown, Label} from "@heroui/react";

Controlled Open State

Dropdown is: closed

"use client";

import {Button, Dropdown, Label} from "@heroui/react";
import {useState} from "react";

Custom Trigger

import {ArrowRightFromSquare, Gear, Persons} from "@gravity-ui/icons";
import {Avatar, Dropdown, Label} from "@heroui/react";

export function CustomTrigger() {
  return (

Styling

Passing Tailwind CSS classes

import { Dropdown, Button } from '@heroui/react';

function CustomDropdown() {
  return (
    <Dropdown>
      <Dropdown.Trigger className="rounded-lg border p-2 bg-surface">
        <Button>Actions</Button>
      </Dropdown.Trigger>
      <Dropdown.Popover className="min-w-[200px]">
        <Dropdown.Menu>
          <Dropdown.Item id="item-1" textValue="Item 1" className="hover:bg-surface-secondary">
            Item 1
          </Dropdown.Item>
        </Dropdown.Menu>
      </Dropdown.Popover>
    </Dropdown>
  );
}

Customizing the component classes

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;
  }
}

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

The Dropdown component uses Menu, MenuItem, and MenuSection as base components. These classes are also available for customization:

  • .menu - Base menu container (menu.css)
    • [data-slot="separator"] - Separator elements within the menu
  • .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
  • .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)

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

PropTypeDefaultDescription
isOpenboolean-Sets the open state of the menu (controlled)
defaultOpenboolean-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
classNamestring-Additional CSS classes
childrenReactNode-Dropdown content
PropTypeDefaultDescription
classNamestring-Additional CSS classes
childrenReactNode | RenderFunction-Trigger content or render function

All Button props are also supported when using a Button as the trigger.

PropTypeDefaultDescription
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
classNamestring-Additional CSS classes
childrenReactNode-Content children

All Popover props are also supported.

PropTypeDefaultDescription
selectionMode"single" | "multiple" | "none""none"Whether single or multiple selection is enabled
selectedKeysIterable<Key>-The currently selected keys (controlled)
defaultSelectedKeysIterable<Key>-The initial selected keys (uncontrolled)
onSelectionChange(keys: Selection) => void-Handler called when the selection changes
disabledKeysIterable<Key>-Keys of disabled items
onAction(key: Key) => void-Handler called when an item is activated
classNamestring-Additional CSS classes
childrenReactNode-Menu content

All Menu props are also supported.

PropTypeDefaultDescription
selectionMode"single" | "multiple"-Selection mode for items within this section
selectedKeysIterable<Key>-The currently selected keys (controlled)
defaultSelectedKeysIterable<Key>-The initial selected keys (uncontrolled)
onSelectionChange(keys: Selection) => void-Handler called when the selection changes
disabledKeysIterable<Key>-Keys of disabled items
classNamestring-Additional CSS classes
childrenReactNode-Section content

All MenuSection props are also supported.

PropTypeDefaultDescription
idKey-Unique identifier for the item
textValuestring-Text content of the item for typeahead
variant"default" | "danger""default"Visual variant of the item
classNamestring-Additional CSS classes
childrenReactNode | RenderFunction-Item content or render function

All MenuItem props are also supported.

PropTypeDefaultDescription
type"checkmark" | "dot""checkmark"Type of indicator to display
classNamestring-Additional CSS classes
childrenReactNode | RenderFunction-Custom indicator content or render function

When using a render function, these values are provided:

PropTypeDescription
isSelectedbooleanWhether the item is selected
isIndeterminatebooleanWhether the item is in an indeterminate state
PropTypeDefaultDescription
classNamestring-Additional CSS classes
childrenReactNode-Custom indicator content
PropTypeDefaultDescription
classNamestring-Additional CSS classes
childrenReactNode-Submenu trigger content

All SubmenuTrigger props are also supported.

RenderProps

When using render functions with Dropdown.Item, these values are provided:

PropTypeDescription
isSelectedbooleanWhether the item is selected
isFocusedbooleanWhether the item is focused
isDisabledbooleanWhether the item is disabled
isPressedbooleanWhether 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.

On this page