Select
Select 从 HeroUI v2 到 v3 的迁移指南。
完整的 API 参考、样式指南与高级示例请参阅 v3 Select 文档。本指南只关注从 HeroUI v2 的迁移。
结构变化
在 v2 中,Select 通过 prop 构成简单结构:
import { Select, SelectItem } from "@lenso/ui";
export default function App() { return ( <Select label="Select animal" placeholder="Choose one"> <SelectItem key="cat">Cat</SelectItem> <SelectItem key="dog">Dog</SelectItem> </Select> );}在 v3 中,Select 需要使用复合组件,并通过 ListBox 渲染菜单项:
import { Select, Label, ListBox } from "@lenso/ui";
export default function App() { return ( <Select placeholder="Choose one"> <Label>Select animal</Label> <Select.Trigger> <Select.Value /> <Select.Indicator /> </Select.Trigger> <Select.Popover> <ListBox> <ListBox.Item id="cat" textValue="Cat"> Cat <ListBox.ItemIndicator /> </ListBox.Item> <ListBox.Item id="dog" textValue="Dog"> Dog <ListBox.ItemIndicator /> </ListBox.Item> </ListBox> </Select.Popover> </Select> );}关键变化
1. 组件结构
v2: 简单的 Select,子节点为 SelectItem
v3: 复合组件(Select.Trigger、Select.Value、Select.ClearButton、Select.Indicator、Select.Popover)与用于菜单项的 ListBox
2. 菜单项组件
v2: SelectItem、SelectSection
v3: ListBox.Item、ListBox.Section(分组标题使用 Header,分组之间使用 Separator)
3. Prop 变更
| v2 prop | v3 位置 | 说明 |
|---|---|---|
selectedKeys | value | 从 Set / 数组改为单个值或数组 |
onSelectionChange | onChange | 已重命名的事件处理函数 |
defaultSelectedKeys | defaultValue | 已重命名的 prop |
label | — | 使用 Label 组件 |
description | — | 使用 Description 组件 |
errorMessage | — | 使用 FieldError 组件 |
variant | variant | 仅保留 primary | secondary |
color | — | 已移除(请使用 Tailwind CSS) |
size | — | 已移除(请使用 Tailwind CSS) |
radius | — | 已移除(请使用 Tailwind CSS) |
classNames | — | 在各子组件上使用 className prop |
startContent | — | 直接自定义 Select.Trigger |
endContent | — | 直接自定义 Select.Trigger |
selectorIcon | — | 自定义 Select.Indicator 的 children |
isClearable | Select.ClearButton | 内置子组件;不要在 Select.Trigger 内嵌套 <button> |
renderValue | — | 使用 Select.Value 的渲染 prop |
labelPlacement | — | 标签始终在外部 |
isRequired | isRequired | 仍然可用 |
disabledKeys | disabledKeys | 仍然可用 |
isOpen | isOpen | 新增:受控地控制 Popover 的打开状态 |
defaultOpen | defaultOpen | 新增:非受控的默认打开状态 |
onOpenChange | onOpenChange | 新增:打开状态变化时触发 |
selectionMode | selectionMode | 仍然可用 |
disableAnimation | — | 已移除(动画机制已不同) |
popoverProps、listboxProps、scrollShadowProps | — | 直接在 Select.Popover、ListBox 等组件上传入 prop |
迁移示例
选择
import { useState } from "react";
{/* Single selection */}const [singleValue, setSingleValue] = useState(new Set([]));<Select selectedKeys={singleValue} onSelectionChange={setSingleValue} label="Select animal"> <SelectItem key="cat">Cat</SelectItem> <SelectItem key="dog">Dog</SelectItem></Select>
{/* Multiple selection */}const [multiValue, setMultiValue] = useState(new Set([]));<Select selectionMode="multiple" selectedKeys={multiValue} onSelectionChange={setMultiValue} label="Select animals"> <SelectItem key="cat">Cat</SelectItem> <SelectItem key="dog">Dog</SelectItem></Select>表单校验
{/* With description */}<Select label="Select animal" description="Choose your favorite" placeholder="Choose one"> <SelectItem key="cat">Cat</SelectItem></Select>
{/* With validation */}<Select isInvalid errorMessage="Please select an option" label="Select animal"> <SelectItem key="cat">Cat</SelectItem></Select>带分组
import { Select, SelectItem, SelectSection } from "@lenso/ui";
<Select label="Select animal"> <SelectSection title="Mammals"> <SelectItem key="cat">Cat</SelectItem> <SelectItem key="dog">Dog</SelectItem> </SelectSection> <SelectSection title="Birds"> <SelectItem key="eagle">Eagle</SelectItem> <SelectItem key="parrot">Parrot</SelectItem> </SelectSection></Select>受控的打开状态
{/* v2 不支持受控的打开状态 */}<Select label="Select animal"> <SelectItem key="cat">Cat</SelectItem> <SelectItem key="dog">Dog</SelectItem></Select>禁用选项
import { Select, SelectItem } from "@lenso/ui";
<Select label="Select animal" disabledKeys={["dog"]}> <SelectItem key="cat">Cat</SelectItem> <SelectItem key="dog">Dog</SelectItem> <SelectItem key="parrot">Parrot</SelectItem></Select>必填
import { Select, SelectItem } from "@lenso/ui";
<Select isRequired label="Select animal"> <SelectItem key="cat">Cat</SelectItem> <SelectItem key="dog">Dog</SelectItem></Select>自定义指示器
<Select selectorIcon={<CustomIcon />} label="Select animal"> <SelectItem key="cat">Cat</SelectItem></Select>组件剖析
v3 Select 的结构如下:
Select (Root) ├── Label (optional) ├── Select.Trigger │ ├── Select.Value │ ├── Select.ClearButton(可选) │ └── Select.Indicator ├── Description (optional) ├── Select.Popover │ └── ListBox │ ├── ListBox.Item │ │ ├── Label (optional) │ │ ├── Description (optional) │ │ └── ListBox.ItemIndicator │ ├── ListBox.Section (optional) │ │ ├── Header (section title) │ │ └── ListBox.Item │ └── Separator (optional, between sections) └── FieldError (optional)重要说明
菜单项标识
- v2: React 的
key同时用于列表协调与选择时的项标识。 - v3: 在
ListBox.Item上使用id(状态 / 焦点)与textValue(无障碍);列表协调仍使用 React 的key。
选择值的类型
- v2:
selectedKeys为Set<Key>或数组 - v3: 单选时
value为Key | null,多选时为Key[]
清除按钮
isClearable prop 已移除。请在 Select.Trigger 内使用 Select.ClearButton。不要在触发器内嵌套 <button> — Select.Trigger 本身已经是 button。
清除控件面向指针操作;触发器同时支持按 Backspace 或 Delete 清除,以便键盘与屏幕阅读器用户使用。
<Select value={value} onChange={setValue}> <Select.Trigger> <Select.Value /> <Select.ClearButton /> <Select.Indicator /> </Select.Trigger> {/* ... */}</Select>总结
- 组件结构:必须使用复合组件(
Select.Trigger、Select.Value、Select.ClearButton、Select.Indicator、Select.Popover)。 - 菜单项组件:
SelectItem→ListBox.Item,SelectSection→ListBox.Section(分组标题用Header,分组之间用Separator)。 - 标签 / 描述 / 错误:使用独立组件,而不是对应 prop。
- 选择相关 prop:
selectedKeys/onSelectionChange→value/onChange。 - 受控的打开状态:新增
isOpen、defaultOpen、onOpenChange用于控制 Popover 的打开状态。 - 禁用选项:仍支持
disabledKeys以禁用指定菜单项。 - 必填:仍支持
isRequired标记字段为必填。 - 样式:
variant仅保留primary|secondary;color、size、radius已移除,请用 Tailwind CSS 扩展。 - classNames 已移除:在各子组件上使用
classNameprop。 - 内容类 prop 已移除:
startContent、endContent需通过自定义触发器实现。 - 清除按钮:
isClearable已移除,请在Select.Trigger内使用Select.ClearButton(不要嵌套<button>)。 - 自定义值:用
Select.Value的渲染 prop 替代renderValue。