Skip to content
Lenso UI

Dropdown

Dropdown 从 HeroUI v2 到 v3 的迁移指南。

完整的 API 参考、样式指南与高级示例请参阅 v3 Dropdown 文档。本指南只关注从 HeroUI v2 的迁移。

结构变化

在 v2 中,Dropdown 使用相互独立的组件:DropdownTrigger、DropdownMenu、DropdownItem、DropdownSection:

import { Dropdown, DropdownTrigger, DropdownMenu, DropdownItem, Button } from "@lenso/ui";
export default function App() {  return (    <Dropdown>      <DropdownTrigger>        <Button>Open Menu</Button>      </DropdownTrigger>      <DropdownMenu>        <DropdownItem key="new">New file</DropdownItem>        <DropdownItem key="copy">Copy link</DropdownItem>      </DropdownMenu>    </Dropdown>  );}

在 v3 中,Dropdown 采用复合组件模式,并提供显式的子组件结构:

import { Dropdown, Button, Label } from "@lenso/ui";
export default function App() {  return (    <Dropdown>      <Button>Open Menu</Button>      <Dropdown.Popover>        <Dropdown.Menu>          <Dropdown.Item id="new" textValue="New file">            <Label>New file</Label>          </Dropdown.Item>          <Dropdown.Item id="copy" textValue="Copy link">            <Label>Copy link</Label>          </Dropdown.Item>        </Dropdown.Menu>      </Dropdown.Popover>    </Dropdown>  );}

主要变化

1. 组件结构

v2: 相互独立的组件:DropdownTrigger、DropdownMenu、DropdownItem、DropdownSection
v3: 复合组件:Dropdown.Trigger、Dropdown.Popover、Dropdown.Menu、Dropdown.Item、Dropdown.Section

2. 组件名称变更

v2 组件v3 组件说明
DropdownTriggerDropdown.Trigger功能相同
DropdownMenuDropdown.Menu需包裹在 Dropdown.Popover 内
DropdownItemDropdown.Item使用 id 与 textValue;列表项保留 key
DropdownSectionDropdown.Section功能相同
—Dropdown.Popover新增包裹组件(必填)

3. 菜单项标识

v2: 菜单项内容通过 children 传递;React 的 key 同时用于列表调和与菜单项标识(选择、焦点)。
v3: 菜单项的可见文本必须使用 Label 组件。为每个菜单项提供 id(状态/焦点)与 textValue(当内容不是纯文本时用于无障碍)。列表中的菜单项仍应保留 React 的 key。

4. Prop 变更

v2 propv3 位置说明
variant、color(在 DropdownMenu 上)—已移除(菜单不再有 variant/color)
classNames、itemClasses(在 DropdownMenu 上)—在 Menu 与菜单项上使用 className
color(在 DropdownItem 上)Dropdown.Item使用 variant="danger" 表示危险操作
title—使用 Label 子组件
description—使用 Description 子组件
shortcut—使用 Kbd 子组件
startContent、endContent—将图标或组件作为 children 放置
selectedIcon—使用 Dropdown.ItemIndicator
showDivider—在菜单项之间使用 Separator
classNames(在 DropdownItem 上)—在菜单项上使用 className
isSelectedDropdown.Menu在 Menu 上使用 selectedKeys
isDisabledDropdown.Menu在 Menu 上使用 disabledKeys
trigger(在 Dropdown 上)Dropdown仍支持:"press"(默认)或 "longPress"

5. 新增子组件

  • Dropdown.Popover:Dropdown.Menu 的必填外层包裹
  • Dropdown.ItemIndicator:用于选择指示(对勾/圆点等)
  • Dropdown.SubmenuTrigger:子菜单触发结构
  • Dropdown.SubmenuIndicator:子菜单 chevron 指示

迁移示例

使用 onAction

<DropdownMenu onAction={(key) => alert(key)}>  <DropdownItem key="new">New file</DropdownItem></DropdownMenu>

菜单项内容

{/* With icon */}<DropdownItem  key="new"  startContent={<AddNoteIcon />}>  New file</DropdownItem>
{/* With description */}<DropdownItem  key="edit"  description="Edit the file">  Edit file</DropdownItem>
{/* With shortcut */}<DropdownItem  key="copy"  shortcut="⌘C">  Copy</DropdownItem>

危险菜单项

<DropdownItem  key="delete"  className="text-danger"  color="danger">  Delete file</DropdownItem>

使用分组(Section)

<DropdownMenu>  <DropdownSection showDivider title="Actions">    <DropdownItem key="new">New file</DropdownItem>    <DropdownItem key="edit">Edit file</DropdownItem>  </DropdownSection>  <DropdownSection title="Danger zone">    <DropdownItem key="delete" color="danger">Delete file</DropdownItem>  </DropdownSection></DropdownMenu>

选择

import { useState } from "react";
{/* Single selection */}const [singleSelected, setSingleSelected] = useState(new Set(["text"]));<DropdownMenu  selectedKeys={singleSelected}  selectionMode="single"  onSelectionChange={setSingleSelected}>  <DropdownItem key="text">Text</DropdownItem>  <DropdownItem key="number">Number</DropdownItem></DropdownMenu>
{/* Multiple selection */}const [multiSelected, setMultiSelected] = useState(new Set(["bold"]));<DropdownMenu  selectedKeys={multiSelected}  selectionMode="multiple"  onSelectionChange={setMultiSelected}>  <DropdownItem key="bold">Bold</DropdownItem>  <DropdownItem key="italic">Italic</DropdownItem></DropdownMenu>

键盘快捷键

<DropdownItem key="copy" shortcut="⌘C">  Copy</DropdownItem>

子菜单

{/* v2 did not have built-in submenu support */}

长按触发

<Dropdown>  <DropdownTrigger>    <Button>Long press me</Button>  </DropdownTrigger>  <DropdownMenu>    <DropdownItem key="cut">Cut</DropdownItem>    <DropdownItem key="copy">Copy</DropdownItem>  </DropdownMenu></Dropdown>

组件结构(Anatomy)

v3 的 Dropdown 结构如下:

Dropdown (Root) — accepts trigger="press" | "longPress"  ├── Dropdown.Trigger (optional, defaults to first child)  ├── Dropdown.Popover (required wrapper)  │   └── Dropdown.Menu  │       ├── Dropdown.Item  │       │   ├── Icon (optional, first child)  │       │   ├── Label (required for text)  │       │   ├── Description (optional)  │       │   ├── Kbd slot="keyboard" (optional, for shortcuts)  │       │   └── Dropdown.ItemIndicator (optional, for selection)  │       ├── Separator (for dividers)  │       ├── Dropdown.Section  │       │   ├── Header (optional)  │       │   └── Dropdown.Item  │       └── Dropdown.SubmenuTrigger  │           ├── Dropdown.Item  │           │   ├── Label  │           │   └── Dropdown.SubmenuIndicator (chevron icon)  │           └── Dropdown.Popover  │               └── Dropdown.Menu  │                   └── Dropdown.Item

总结

  1. 组件结构:必须使用复合组件(Dropdown.Trigger、Dropdown.Popover、Dropdown.Menu 等)。
  2. Dropdown.Popover 为必填:Dropdown.Menu 必须包裹在 Dropdown.Popover 内。
  3. Label 组件:菜单项文本必须使用 Label。
  4. Description 组件:用 Description 替代 description prop。
  5. Kbd 组件:用带 slot="keyboard" 的 Kbd 替代 shortcut prop;slot 用于把快捷键放到菜单项末尾。
  6. 图标作为 children:图标作为第一个 child 放置,不再使用 startContent prop。
  7. Separator 组件:用 Separator 替代 showDivider prop。
  8. ItemIndicator 组件:用 Dropdown.ItemIndicator 表示选择状态。
  9. 用 variant 表示危险:用 variant="danger" 替代 color="danger"。
  10. 菜单样式 prop 移除:Dropdown.Menu 不再支持 variant 或 color prop。
  11. classNames 移除:在各自子组件上使用 className。
  12. 子菜单:用 Dropdown.SubmenuTrigger 包裹会打开嵌套菜单的项,并在项内使用 Dropdown.SubmenuIndicator。
  13. trigger prop:在根 Dropdown 上使用 trigger="longPress" 以长按打开菜单(默认为按压打开)。