JGuang / HeroUI

Dropdown 下拉菜单

下拉菜单展示一组可供用户选择的操作或选项。

引入

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

用法

HeroUI 示例

组件结构

引入 Dropdown 组件并通过点语法访问所有子部分。

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

带单选

HeroUI 示例

单选且自定义指示器

HeroUI 示例

带多选

HeroUI 示例

带分组级选择

HeroUI 示例

带键盘快捷键

HeroUI 示例

带图标

HeroUI 示例

长按触发

HeroUI 示例

带描述

HeroUI 示例

带分组

HeroUI 示例

带禁用项

HeroUI 示例

带子菜单

HeroUI 示例

带自定义子菜单指示器

HeroUI 示例

受控

HeroUI 示例

受控展开状态

HeroUI 示例

自定义触发器

HeroUI 示例

样式

传入 Tailwind CSS 类

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

自定义组件类

若要自定义 Dropdown 组件类,可使用 @layer components 指令。

了解更多。

@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 方法论,确保组件变体和状态可复用且易于自定义。

CSS 类

Dropdown 组件使用以下 CSS 类(查看源码样式):

基础类

  • .dropdown - Dropdown 根容器
  • .dropdown__trigger - 用于触发 Dropdown 的按钮或元素
  • .dropdown__popover - Popover 容器
  • .dropdown__menu - Popover 内的菜单容器

状态类

  • .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 作为底层组件。以下类名也可用于自定义:

  • .menu - 菜单容器(menu.css)
    • [data-slot="separator"] - 菜单内的分隔线元素
  • .menu-item - 菜单项容器(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 - 危险样式变体
  • .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)

交互状态

该组件同时支持 CSS 伪类和 data 属性,便于灵活组合:

  • 悬停:触发器与菜单项上 :hover 或 [data-hovered="true"]
  • 聚焦:触发器与菜单项上 :focus-visible 或 [data-focus-visible="true"]
  • 禁用:触发器与菜单项上 :disabled 或 [data-disabled="true"]
  • 按下:触发器与菜单项上 :active 或 [data-pressed="true"]
  • 选中:菜单项上 [data-selected="true"] 或 [aria-selected="true"]

API 参考

Prop类型默认值描述
isOpenboolean-设置菜单展开状态(受控)。
defaultOpenboolean-设置菜单默认展开状态(非受控)。
onOpenChange(isOpen: boolean) => void-展开状态变化时调用的事件处理函数。
trigger"press" | "longPress""press"触发菜单的交互类型。
classNamestring-额外的 Tailwind CSS 类。
childrenReactNode-Dropdown 内容。
Prop类型默认值描述
classNamestring-额外的 Tailwind CSS 类。
childrenReactNode | RenderFunction-触发器内容或渲染函数。

使用 Button 作为触发器时,同样支持所有 Button props。

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 位置。
classNamestring-额外的 Tailwind CSS 类。
childrenReactNode-子内容。

同样支持所有 Popover props。

Prop类型默认值描述
selectionMode"single" | "multiple" | "none""none"是否启用单选、多选或不启用选择。
selectedKeysIterable-当前选中的 key(受控)。
defaultSelectedKeysIterable-初始选中的 key(非受控)。
onSelectionChange(keys: Selection) => void-选中变化时调用的事件处理函数。
disabledKeysIterable-禁用项的 key。
onAction(key: Key) => void-激活菜单项时调用的事件处理函数。
classNamestring-额外的 Tailwind CSS 类。
childrenReactNode-菜单内容。

同样支持所有 Menu props。

Prop类型默认值描述
selectionMode"single" | "multiple"-该分组内菜单项的选择模式。
selectedKeysIterable-当前选中的 key(受控)。
defaultSelectedKeysIterable-初始选中的 key(非受控)。
onSelectionChange(keys: Selection) => void-选中变化时调用的事件处理函数。
disabledKeysIterable-禁用项的 key。
classNamestring-额外的 Tailwind CSS 类。
childrenReactNode-分组内容。

同样支持所有 MenuSection props。

Prop类型默认值描述
idKey-菜单项唯一标识。
textValuestring-用于首字母导航的文本内容。
variant"default" | "danger""default"菜单项视觉变体。
classNamestring-额外的 Tailwind CSS 类。
childrenReactNode | RenderFunction-菜单项内容或渲染函数。

同样支持所有 MenuItem props。

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

使用渲染函数时,会传入以下值:

Prop类型描述
isSelectedboolean该项是否选中。
isIndeterminateboolean该项是否处于不确定状态。
Prop类型默认值描述
classNamestring-额外的 Tailwind CSS 类。
childrenReactNode-自定义指示器内容。
Prop类型默认值描述
classNamestring-额外的 Tailwind CSS 类。
childrenReactNode-子菜单触发器内容。

同样支持所有 SubmenuTrigger props。

RenderProps

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

Prop类型描述
isSelectedboolean该项是否选中。
isFocusedboolean该项是否聚焦。
isDisabledboolean该项是否禁用。
isPressedboolean该项是否处于按下状态。

示例

基础用法

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>

带分组

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>

受控选择

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

带子菜单

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 文档。

本地来源: vendor/zh/react/components/(collections)/dropdown.mdx

文档根据 HeroUI v3 固定提交生成,已调整内部链接与交互预览以适配 JGuang。

On this page