Skip to content
Lenso UI

Autocomplete

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

在 v3 中,v2 的 Autocomplete 可以迁移为 v3 Autocomplete 或 v3 ComboBox,取决于你的使用场景。请参阅下文「何时使用 Autocomplete 与 ComboBox」。本指南只关注从 HeroUI v2 的迁移。

何时使用 Autocomplete 与 ComboBox

v3 提供两个组件来替代 v2 的 Autocomplete:

组件适用场景输入方式底层实现
Autocomplete选择器式交互,Popover 内带搜索 / 筛选字段按钮触发器展示已选值;Popover 内为搜索输入React Aria Select + Autocomplete
ComboBox在可见输入框中输入以筛选下拉列表内联文本输入与下拉触发器React Aria ComboBox

使用 Autocomplete:用户从预定义列表中选择,且搜索字段应出现在下拉内(类似可搜索的选择器)。

使用 ComboBox:用户在可见输入框中直接输入以筛选或搜索选项(行为最接近 v2)。

结构变化

在 v2 中,Autocomplete 是内部包装 Input 的单一组件:

import { Autocomplete, AutocompleteItem } from "@lenso/ui";
export default function App() {  return (    <Autocomplete label="Select an animal">      <AutocompleteItem key="cat">Cat</AutocompleteItem>      <AutocompleteItem key="dog">Dog</AutocompleteItem>    </Autocomplete>  );}

迁移到 v3 ComboBox(最接近 v2)

ComboBox 提供与 v2 Autocomplete 最接近的体验:内联文本输入并随输入筛选选项。

import { ComboBox, Input, Label, ListBox } from "@lenso/ui";
export default function App() {  return (    <ComboBox>      <Label>Select an animal</Label>      <ComboBox.InputGroup>        <Input placeholder="Search animals..." />        <ComboBox.Trigger />      </ComboBox.InputGroup>      <ComboBox.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>      </ComboBox.Popover>    </ComboBox>  );}

迁移到 v3 Autocomplete(可搜索的选择器)

Autocomplete 提供选择器式触发器,并在 Popover 内提供搜索 / 筛选字段:

import { Autocomplete, Label, SearchField, ListBox, useFilter } from "@lenso/ui";
export default function App() {  const { contains } = useFilter({ sensitivity: "base" });
  return (    <Autocomplete>      <Label>Select an animal</Label>      <Autocomplete.Trigger>        <Autocomplete.Value />        <Autocomplete.ClearButton />        <Autocomplete.Indicator />      </Autocomplete.Trigger>      <Autocomplete.Popover>        <Autocomplete.Filter filter={contains}>          <SearchField>            <SearchField.Group>              <SearchField.SearchIcon />              <SearchField.Input placeholder="Search..." />            </SearchField.Group>          </SearchField>          <ListBox>            <ListBox.Item id="cat" textValue="Cat">              Cat              <ListBox.ItemIndicator />            </ListBox.Item>            <ListBox.Item id="dog" textValue="Dog">              Dog              <ListBox.ItemIndicator />            </ListBox.Item>          </ListBox>        </Autocomplete.Filter>      </Autocomplete.Popover>    </Autocomplete>  );}

关键变化

1. 两个替代组件

v2: Autocomplete(单一组件)
v3: ComboBox(内联输入 + 下拉)或 Autocomplete(选择器式 + Popover 内搜索)

2. 组件结构

v2: 单一组件,内部包含 Input
v3 ComboBox: 复合组件(ComboBox.InputGroup、ComboBox.Trigger、ComboBox.Popover)
v3 Autocomplete: 复合组件(Autocomplete.Trigger、Autocomplete.Value、Autocomplete.ClearButton、Autocomplete.Indicator、Autocomplete.Popover、Autocomplete.Filter)

3. 菜单项组件

v2: AutocompleteItem、AutocompleteSection
v3: ListBox.Item、ListBox.Section(来自 ListBox)

4. 菜单项标识

v2: React 的 key 同时用于列表协调与选择时的项标识。
v3: 在 ListBox.Item 上使用 id 与 textValue(状态与无障碍);列表中的项仍保留 React 的 key。

5. Autocomplete 专用子组件(v3)

v3 Autocomplete 引入 v2 中不存在的子组件:

子组件用途
Autocomplete.Trigger打开 Popover 的按钮组
Autocomplete.Value显示当前选中值或占位符
Autocomplete.ClearButton清除当前选择
Autocomplete.Indicator下拉箭头图标(打开时旋转)
Autocomplete.Popover下拉 Popover 容器
Autocomplete.Filter包裹 SearchField 与 ListBox 以启用筛选;接受 filter 函数、inputValue、onInputChange

6. SearchField 集成

v3 Autocomplete 在 Autocomplete.Filter 内使用 SearchField,作为 Popover 中的搜索输入:

<Autocomplete.Filter filter={contains}>  <SearchField>    <SearchField.Group>      <SearchField.SearchIcon />      <SearchField.Input placeholder="Search..." />    </SearchField.Group>  </SearchField>  <ListBox>...</ListBox></Autocomplete.Filter>

SearchField 还有子组件:SearchField.Group、SearchField.Input、SearchField.SearchIcon、SearchField.ClearButton。

7. useFilter Hook

v3 Autocomplete 使用 useFilter hook(来自 React Aria,由 @lenso/ui 再导出)提供带区域设置感知的筛选函数:

import { useFilter } from "@lenso/ui";
const { contains } = useFilter({ sensitivity: "base" });
// 传给 Autocomplete.Filter<Autocomplete.Filter filter={contains}>  ...</Autocomplete.Filter>

该 hook 返回 contains、startsWith、endsWith。sensitivity 控制区域设置感知匹配("base"、"accent"、"case"、"variant")。

8. Prop 变更(ComboBox)

v2 propv3 位置说明
—id(在 ListBox.Item 上)状态用的项标识
—textValue(在 ListBox.Item 上)无障碍(提前输入)
labelLabel使用 Label 组件
descriptionDescription使用 Description 组件
placeholderInput写在 Input 的 placeholder
selectedKey、onSelectionChange、inputValue、onInputChangeComboBox与 v2 相同
allowsCustomValue、allowsEmptyCollection、defaultFilterComboBox与 v2 相同
disabledKeys、isDisabled、isRequired、isInvalid、nameComboBox与 v2 相同
menuTriggerComboBox"focus"(默认)、"input" 或 "manual"
variant、color、size、radius—已移除(请使用 Tailwind CSS)
labelPlacement—已移除(请自行摆放 Label)
startContent、endContent—加到 Input 或 InputGroup
selectorIcon、clearIcon—自定义 ComboBox.Trigger 或手动实现
isClearable—手动实现
showScrollIndicators—已移除
classNames—在各部件上使用 className
popoverProps、listboxProps、inputProps—直接在对应子组件上配置
scrollShadowProps、scrollRef—已移除
selectorButtonProps、clearButtonProps、disableSelectorIconRotation—已移除
isReadOnlyComboBoxComboBox 上的 isReadOnly prop
fullWidthComboBoxComboBox 上的 fullWidth prop
isVirtualized、maxListboxHeight、itemHeight—已移除
onClose、onClear—改用其他事件处理函数
validationBehavior、validateComboBox写在 ComboBox 上的 prop

9. Prop 变更(Autocomplete)

v2 propv3 位置说明
—id(在 ListBox.Item 上)状态用的项标识
—textValue(在 ListBox.Item 上)无障碍(提前输入)
labelLabel使用 Label 组件
descriptionDescription使用 Description 组件
placeholderAutocomplete根组件上的 placeholder prop
selectedKey / onSelectionChangevalue / onChangeAutocomplete 上已重命名
selectionModeAutocomplete"single"(默认)或 "multiple"
inputValue、onInputChangeAutocomplete.Filter写在 Filter 上的 inputValue 与 onInputChange
disabledKeys、isDisabled、isRequired、isInvalid、nameAutocomplete与 v2 相同
variant、color、size、radius—已移除(请使用 Tailwind CSS);variant 支持 "primary" / "secondary"
isClearableAutocomplete.ClearButton内置子组件
selectorIconAutocomplete.Indicator将自定义图标作为 children 传入
onClearAutocomplete根组件上的 onClear prop
fullWidthAutocomplete根组件上的 fullWidth prop
classNames—在各部件上使用 className
popoverProps、listboxProps、inputProps—直接在对应子组件上配置

迁移示例

受控选择(ComboBox)

import { useState } from "react";
const [selectedKey, setSelectedKey] = useState("cat");
<Autocomplete  selectedKey={selectedKey}  onSelectionChange={setSelectedKey}  label="Animal">  <AutocompleteItem key="cat">Cat</AutocompleteItem>  <AutocompleteItem key="dog">Dog</AutocompleteItem></Autocomplete>

受控选择(Autocomplete)

import { useState } from "react";
const [selectedKey, setSelectedKey] = useState("cat");
<Autocomplete  selectedKey={selectedKey}  onSelectionChange={setSelectedKey}  label="Animal">  <AutocompleteItem key="cat">Cat</AutocompleteItem>  <AutocompleteItem key="dog">Dog</AutocompleteItem></Autocomplete>

带分组

<Autocomplete label="Country">  <AutocompleteSection title="North America">    <AutocompleteItem key="usa">United States</AutocompleteItem>    <AutocompleteItem key="canada">Canada</AutocompleteItem>  </AutocompleteSection>  <AutocompleteSection title="Europe">    <AutocompleteItem key="uk">United Kingdom</AutocompleteItem>  </AutocompleteSection></Autocomplete>

使用 useFilter(Autocomplete)

{/* v2 在内部处理筛选 */}<Autocomplete label="Animal">  <AutocompleteItem key="cat">Cat</AutocompleteItem>  <AutocompleteItem key="dog">Dog</AutocompleteItem></Autocomplete>

表单校验

{/* Required field */}<Autocomplete label="Animal" isRequired>  <AutocompleteItem key="cat">Cat</AutocompleteItem></Autocomplete>
{/* With error message */}<Autocomplete  label="Animal"  isInvalid  errorMessage="Please select an animal">  <AutocompleteItem key="cat">Cat</AutocompleteItem></Autocomplete>

组件剖析

ComboBox 剖析

ComboBox (Root)  ├── Label  ├── ComboBox.InputGroup  │   ├── Input  │   └── ComboBox.Trigger  ├── Description (optional)  ├── ComboBox.Popover  │   └── ListBox  │       ├── ListBox.Item  │       │   ├── [Content]  │       │   └── ListBox.ItemIndicator (optional)  │       └── ListBox.Section (optional)  │           ├── Header  │           └── ListBox.Item  └── FieldError (optional)

Autocomplete 剖析

Autocomplete (Root)  ├── Label  ├── Autocomplete.Trigger  │   ├── Autocomplete.Value  │   ├── Autocomplete.ClearButton  │   └── Autocomplete.Indicator  ├── Description (optional)  ├── Autocomplete.Popover  │   └── Autocomplete.Filter  │       ├── SearchField  │       │   └── SearchField.Group  │       │       ├── SearchField.SearchIcon  │       │       └── SearchField.Input  │       └── ListBox  │           ├── ListBox.Item  │           │   ├── [Content]  │           │   └── ListBox.ItemIndicator (optional)  │           └── ListBox.Section (optional)  │               ├── Header  │               └── ListBox.Item  └── FieldError (optional)

总结

  1. 两个替代组件:v2 Autocomplete 可迁移为 v3 ComboBox(内联输入)或 v3 Autocomplete(Popover 内可筛选的选择器)。
  2. 组件结构:由带 prop 的单一组件变为带显式子节点的复合组件。
  3. 菜单项组件:AutocompleteItem → ListBox.Item;AutocompleteSection → ListBox.Section。
  4. 菜单项标识:在项上使用 id 与 textValue;列表协调仍用 React 的 key。
  5. 输入:v3 ComboBox 需要显式 Input;v3 Autocomplete 在 Autocomplete.Filter 内使用 SearchField。
  6. 标签 / 描述:对应 prop 拆为独立的 Label 与 Description 组件。
  7. 筛选:v3 Autocomplete 通过 Autocomplete.Filter 与 useFilter 做区域设置感知筛选;v3 ComboBox 使用 defaultFilter prop。
  8. 清除按钮:v3 Autocomplete 内置 Autocomplete.ClearButton;v3 ComboBox 需手动实现。
  9. 选中值展示:v3 Autocomplete 用 Autocomplete.Value 展示选中值,并支持渲染 prop。
  10. 样式类 prop 已移除:color、size、radius 已移除(请使用 Tailwind CSS);variant 现支持 "primary" / "secondary"。
  11. classNames 已移除:在各子组件上使用 className prop。
  12. useFilter Hook:v3 新增,提供 contains、startsWith、endsWith 用于区域设置感知的文本匹配。