---
title: Dropdown 下拉菜单
description: 展示用户可选择的操作或选项列表
links:
  rac: Menu
  source: dropdown/dropdown.tsx
  styles: dropdown.css
  storybook: Components/Collections/Dropdown
---

## 用法

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

<ComponentPreview
  name="dropdown-default"
/>

## 组件结构

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

## 示例

### 带图标

<ComponentPreview
  name="dropdown-with-icons"
/>

### 带描述

<ComponentPreview
  name="dropdown-with-descriptions"
/>

### 含禁用项

<ComponentPreview
  name="dropdown-with-disabled-items"
/>

### 分组选项

<ComponentPreview
  name="dropdown-with-sections"
/>

### 多选

<ComponentPreview
  name="dropdown-with-multiple-selection"
/>

### 受控组件

<ComponentPreview
  name="dropdown-controlled"
/>

### 受控展开状态

<ComponentPreview
  name="dropdown-controlled-open-state"
/>

### 单选

<ComponentPreview
  name="dropdown-with-single-selection"
/>

### 单选自定义指示器

<ComponentPreview
  name="dropdown-single-with-custom-indicator"
/>

### 分组级选择

<ComponentPreview
  name="dropdown-with-section-level-selection"
/>

### 带快捷键

<ComponentPreview
  name="dropdown-with-keyboard-shortcuts"
/>

### 含子菜单

<ComponentPreview
  name="dropdown-with-submenus"
/>

### 自定义子菜单指示器

<ComponentPreview
  name="dropdown-with-custom-submenu-indicator"
/>

### 自定义触发器

<ComponentPreview
  name="dropdown-custom-trigger"
/>

### 长按触发

<ComponentPreview
  name="dropdown-long-press-trigger"
/>

## 自定义样式

### Tailwind CSS

<ComponentPreview name="dropdown-custom-styles" />

### 全局 CSS

可使用 `@layer components` 指令自定义 Dropdown 组件类。
[了解更多](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 遵循 [BEM](https://getbem.com/) 方法论，确保组件变体与状态可复用且易于自定义。

### CSS 类

Dropdown 组件使用以下 CSS 类（[查看源码样式](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/dropdown.css)）：

#### 基础类 [!toc]
- `.dropdown` - Dropdown 根容器
- `.dropdown__trigger` - 触发 Dropdown 的按钮或元素
- `.dropdown__popover` - Popover 容器
- `.dropdown__menu` - Popover 内的菜单容器

#### 状态类 [!toc]
- `.dropdown__trigger[data-focus-visible="true"]` - 触发器聚焦状态
- `.dropdown__trigger[data-disabled="true"]` - 触发器禁用状态
- `.dropdown__trigger[data-pressed="true"]` - 触发器按下状态
- `.dropdown__popover[data-entering]` - 进入动画状态
- `.dropdown__popover[data-exiting]` - 退出动画状态
- `.dropdown__menu[data-selection-mode="single"]` - 单选模式
- `.dropdown__menu[data-selection-mode="multiple"]` - 多选模式

### 菜单组件类

Dropdown 使用 Menu、MenuItem 与 MenuSection 作为底层组件。以下类名也可用于自定义：

#### 菜单类 [!toc]
- `.menu` - 菜单容器（[menu.css](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/menu.css)）
  - `[data-slot="separator"]` - 菜单内的分隔线元素

#### 菜单项类 [!toc]
- `.menu-item` - 菜单项容器（[menu-item.css](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/menu-item.css)）
- `.menu-item__indicator` - 选中指示器（对勾或圆点）
  - `[data-slot="menu-item-indicator--checkmark"]` - 对勾指示器 SVG
  - `[data-slot="menu-item-indicator--dot"]` - 圆点指示器 SVG
- `.menu-item__indicator--submenu` - 子菜单指示器（箭头）
- `.menu-item--default` - 默认样式变体
- `.menu-item--danger` - 危险样式变体

#### 菜单项状态类 [!toc]
- `.menu-item[data-focus-visible="true"]` - 聚焦状态（键盘焦点）
- `.menu-item[data-focus="true"]` - 聚焦状态
- `.menu-item[data-pressed]` - 按下状态
- `.menu-item[data-hovered]` - 悬停状态
- `.menu-item[data-selected="true"]` - 选中状态
- `.menu-item[data-disabled]` - 禁用状态
- `.menu-item[data-has-submenu="true"]` - 带子菜单的项
- `.menu-item[data-selection-mode="single"]` - 单选模式
- `.menu-item[data-selection-mode="multiple"]` - 多选模式
- `.menu-item[aria-checked="true"]` - 已勾选（ARIA）
- `.menu-item[aria-selected="true"]` - 已选中（ARIA）

#### 菜单分区类 [!toc]
- `.menu-section` - 菜单分区容器（[menu-section.css](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/menu-section.css)）

### 交互状态

组件同时支持 CSS 伪类与 data 属性：

- **Hover**：触发器与菜单项上 `:hover` 或 `[data-hovered="true"]`
- **Focus**：触发器与菜单项上 `:focus-visible` 或 `[data-focus-visible="true"]`
- **Disabled**：触发器与菜单项上 `:disabled` 或 `[data-disabled="true"]`
- **Pressed**：触发器与菜单项上 `:active` 或 `[data-pressed="true"]`
- **Selected**：菜单项上 `[data-selected="true"]` 或 `[aria-selected="true"]`

## API 参考

### Dropdown

| Prop | 类型 | 默认值 | 描述 |
|------|------|--------|------|
| `isOpen` | `boolean` | - | 设置菜单展开状态（受控）。 |
| `defaultOpen` | `boolean` | - | 设置菜单默认展开状态（非受控）。 |
| `onOpenChange` | `(isOpen: boolean) => void` | - | 展开状态变化时调用的事件处理函数。 |
| `trigger` | `"press" \| "longPress"` | `"press"` | 触发菜单的交互类型。 |
| `className` | `string` | - | 额外的 Tailwind CSS 类。 |
| `children` | `ReactNode` | - | Dropdown 内容。 |

### Dropdown.Trigger

| Prop | 类型 | 默认值 | 描述 |
|------|------|--------|------|
| `className` | `string` | - | 额外的 Tailwind CSS 类。 |
| `children` | `ReactNode \| RenderFunction` | - | 触发器内容或渲染函数。 |

使用 Button 作为触发器时，同样支持所有 [Button](https://react-spectrum.adobe.com/react-aria/Button.html) props。

### Dropdown.Popover

| Prop | 类型 | 默认值 | 描述 |
|------|------|--------|------|
| `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"` | 相对于触发器的 Popover 位置。 |
| `className` | `string` | - | 额外的 Tailwind CSS 类。 |
| `children` | `ReactNode` | - | 子内容。 |

同样支持所有 [Popover](https://react-spectrum.adobe.com/react-aria/Popover.html) props。

### Dropdown.Menu

| Prop | 类型 | 默认值 | 描述 |
|------|------|--------|------|
| `selectionMode` | `"single" \| "multiple" \| "none"` | `"none"` | 是否启用单选、多选或不启用选择。 |
| `selectedKeys` | `Iterable<Key>` | - | 当前选中的 key（受控）。 |
| `defaultSelectedKeys` | `Iterable<Key>` | - | 初始选中的 key（非受控）。 |
| `onSelectionChange` | `(keys: Selection) => void` | - | 选中变化时调用的事件处理函数。 |
| `disabledKeys` | `Iterable<Key>` | - | 禁用项的 key。 |
| `onAction` | `(key: Key) => void` | - | 激活菜单项时调用的事件处理函数。 |
| `className` | `string` | - | 额外的 Tailwind CSS 类。 |
| `children` | `ReactNode` | - | 菜单内容。 |

同样支持所有 [Menu](https://react-spectrum.adobe.com/react-aria/Menu.html#menu) props。

### Dropdown.Section

| Prop | 类型 | 默认值 | 描述 |
|------|------|--------|------|
| `selectionMode` | `"single" \| "multiple"` | - | 该分组内菜单项的选择模式。 |
| `selectedKeys` | `Iterable<Key>` | - | 当前选中的 key（受控）。 |
| `defaultSelectedKeys` | `Iterable<Key>` | - | 初始选中的 key（非受控）。 |
| `onSelectionChange` | `(keys: Selection) => void` | - | 选中变化时调用的事件处理函数。 |
| `disabledKeys` | `Iterable<Key>` | - | 禁用项的 key。 |
| `className` | `string` | - | 额外的 Tailwind CSS 类。 |
| `children` | `ReactNode` | - | 分组内容。 |

同样支持所有 [MenuSection](https://react-spectrum.adobe.com/react-aria/Menu.html#menusection) props。

### Dropdown.Item

| Prop | 类型 | 默认值 | 描述 |
|------|------|--------|------|
| `id` | `Key` | - | 菜单项唯一标识。 |
| `textValue` | `string` | - | 用于首字母导航的文本内容。 |
| `variant` | `"default" \| "danger"` | `"default"` | 菜单项视觉变体。 |
| `className` | `string` | - | 额外的 Tailwind CSS 类。 |
| `children` | `ReactNode \| RenderFunction` | - | 菜单项内容或渲染函数。 |

同样支持所有 [MenuItem](https://react-spectrum.adobe.com/react-aria/Menu.html#menuitem) props。

### Dropdown.ItemIndicator

| Prop | 类型 | 默认值 | 描述 |
|------|------|--------|------|
| `type` | `"checkmark" \| "dot"` | `"checkmark"` | 指示器类型。 |
| `className` | `string` | - | 额外的 Tailwind CSS 类。 |
| `children` | `ReactNode \| RenderFunction` | - | 自定义指示器内容或渲染函数。 |

使用渲染函数时，会传入以下值：

| Prop | 类型 | 描述 |
|------|------|------|
| `isSelected` | `boolean` | 该项是否选中。 |
| `isIndeterminate` | `boolean` | 该项是否处于不确定状态。 |

### Dropdown.SubmenuIndicator

| Prop | 类型 | 默认值 | 描述 |
|------|------|--------|------|
| `className` | `string` | - | 额外的 Tailwind CSS 类。 |
| `children` | `ReactNode` | - | 自定义指示器内容。 |

### Dropdown.SubmenuTrigger

| Prop | 类型 | 默认值 | 描述 |
|------|------|--------|------|
| `className` | `string` | - | 额外的 Tailwind CSS 类。 |
| `children` | `ReactNode` | - | 子菜单触发器内容。 |

同样支持所有 [SubmenuTrigger](https://react-spectrum.adobe.com/react-aria/Menu.html#submenutrigger) props。

### Render Props

在 Dropdown.Item 中使用渲染函数时，会传入以下值：

| Prop | 类型 | 描述 |
|------|------|------|
| `isSelected` | `boolean` | 该项是否选中。 |
| `isFocused` | `boolean` | 该项是否聚焦。 |
| `isDisabled` | `boolean` | 该项是否禁用。 |
| `isPressed` | `boolean` | 该项是否处于按下状态。 |

## 示例

### 基本用法

```tsx
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>
```

### 代码示例：分组选项

```tsx
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>
```

### 受控选择

```tsx
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>
  );
}
```

### 代码示例：含子菜单

```tsx
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>
```

## 无障碍

Dropdown 组件实现 ARIA 菜单模式，并提供：

- 完整键盘导航（方向键、Home/End、首字母导航）
- 屏幕阅读器对操作与选中变化的播报
- 合理的焦点管理
- 禁用态支持
- 长按交互支持
- 子菜单导航

更多信息见 [React Aria Menu 文档](https://react-spectrum.adobe.com/react-aria/Menu.html#menu)。

## 相关组件

<RelatedComponents component="dropdown" />