Autocomplete 自动完成
结合选择与过滤,让用户从选项列表中搜索并选择
用法
import { Autocomplete, useFilter } from "@heroui/react";组件结构
import {Autocomplete, Label, Description, SearchField, ListBox} from "@heroui/react";
export default () => (
<Autocomplete>
<Label />
<Autocomplete.Trigger>
<Autocomplete.Value />
<Autocomplete.ClearButton />
<Autocomplete.Indicator />
</Autocomplete.Trigger>
<Description />
<Autocomplete.Popover>
<Autocomplete.Filter>
<SearchField>
<SearchField.Group>
<SearchField.SearchIcon />
<SearchField.Input />
</SearchField.Group>
</SearchField>
<ListBox>
<ListBox.Item>
<Label />
<ListBox.ItemIndicator />
</ListBox.Item>
</ListBox>
</Autocomplete.Filter>
</Autocomplete.Popover>
</Autocomplete>
);示例
变体
Autocomplete 组件支持两种视觉变体:
primary(默认)- 标准样式带阴影,适用于大多数场景secondary- 低强调变体无阴影,适用于 Surface 组件内
宽度充满
带描述
必填
禁用
含禁用选项
允许空选项
allowsEmptyCollection 属性允许集合为空时仍可使用自动完成,适用于列表初始为空或全部被过滤掉的场景。
分组选项
多选
受控组件
受控多选
受控展开状态
异步搜索
自定义指示器
自定义展示值
可使用 render props 自定义显示值:
表面样式
在 Surface 组件内使用时,请使用 variant="secondary" 以应用适合 Surface 背景的低强调变体。
虚拟滚动
Autocomplete 通过 Virtualizer 支持虚拟化,仅渲染视口内可见行以高效处理大数据集。
高级示例
用户选择
用户多选
地点搜索
标签组选择
邮件收件人
自定义样式
Tailwind CSS
全局 CSS
可使用 @layer components 指令自定义 Autocomplete 组件类。
了解更多。
@layer components {
.autocomplete {
@apply flex flex-col gap-1;
}
.autocomplete__trigger {
@apply rounded-lg border border-border bg-surface p-2;
}
.autocomplete__value {
@apply text-current;
}
.autocomplete__clear-button {
@apply text-muted hover:text-foreground;
}
.autocomplete__indicator {
@apply text-muted;
}
.autocomplete__popover {
@apply rounded-lg border border-border bg-surface p-2;
}
}样式参考
HeroUI 遵循 BEM 方法论,确保组件变体与状态可复用且易于自定义。
CSS 类
Autocomplete 组件使用以下 CSS 类(查看源码样式):
基础类
.autocomplete- 自动完成根容器.autocomplete__trigger- 触发自动完成的按钮.autocomplete__value- 显示的值或占位符.autocomplete__clear-button- 清除已选值的按钮.autocomplete__indicator- 下拉指示图标.autocomplete__popover- 弹出层容器.autocomplete__filter- 过滤包装器
变体类
.autocomplete--primary- 带阴影的主变体(默认).autocomplete--secondary- 无阴影的次变体,适用于 Surface 内
状态类
.autocomplete[data-invalid="true"]- 无效状态.autocomplete__trigger[data-focus-visible="true"]- 触发器聚焦状态.autocomplete__trigger[data-disabled="true"]- 触发器禁用状态.autocomplete__value[data-placeholder="true"]- 占位符状态.autocomplete__clear-button[data-empty="true"]- 无选择时隐藏清除按钮.autocomplete__indicator[data-open="true"]- 打开时的指示器状态
交互状态
组件同时支持 CSS 伪类与 data 属性:
- Hover:触发器上的
:hover或[data-hovered="true"] - Focus:触发器上的
:focus-visible或[data-focus-visible="true"] - Disabled:Autocomplete 上的
:disabled或[data-disabled="true"] - Open:指示器上的
[data-open="true"]
API 参考
Autocomplete
| Prop | 类型 | 默认值 | 描述 |
|---|---|---|---|
placeholder | string | 'Select an item' | 为空时显示的占位文本 |
selectionMode | "single" | "multiple" | "single" | 启用单选或多选 |
allowsEmptyCollection | boolean | false | 是否允许空集合;为 true 时无选项也可使用 |
isOpen | boolean | - | 弹出层打开状态(受控) |
defaultOpen | boolean | - | 弹出层默认打开状态(非受控) |
onOpenChange | (isOpen: boolean) => void | - | 打开状态变化时的回调 |
disabledKeys | Iterable<Key> | - | 禁用项的 key |
isDisabled | boolean | - | 是否禁用 |
value | Key | Key[] | null | - | 当前值(受控) |
defaultValue | Key | Key[] | null | - | 默认值(非受控) |
onChange | (value: Key | Key[] | null) => void | - | 值变化时的回调 |
isRequired | boolean | - | 是否必填 |
isInvalid | boolean | - | 值是否无效 |
name | string | - | 提交 HTML 表单时使用的名称 |
fullWidth | boolean | false | 是否占满容器宽度 |
variant | "primary" | "secondary" | "primary" | 视觉变体。primary 为默认带阴影样式;secondary 为低强调无阴影,适用于 Surface 内 |
className | string | - | 附加 CSS 类 |
children | ReactNode | RenderFunction | - | 内容或 render 函数 |
Autocomplete.Trigger
| Prop | 类型 | 默认值 | 描述 |
|---|---|---|---|
className | string | - | 附加 CSS 类 |
children | ReactNode | RenderFunction | - | 触发器内容或 render 函数 |
Autocomplete.Value
| Prop | 类型 | 默认值 | 描述 |
|---|---|---|---|
className | string | - | 附加 CSS 类 |
children | ReactNode | RenderFunction | - | 值内容或 render 函数 |
Autocomplete.Indicator
| Prop | 类型 | 默认值 | 描述 |
|---|---|---|---|
className | string | - | 附加 CSS 类 |
children | ReactNode | - | 自定义指示器内容 |
Autocomplete.ClearButton
| Prop | 类型 | 默认值 | 描述 |
|---|---|---|---|
className | string | - | 附加 CSS 类 |
onClick | (e: MouseEvent) => void | - | 点击按钮时的回调 |
ref | RefObject<HTMLButtonElement> | - | 清除按钮元素的 ref |
Autocomplete.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" | 弹出层相对触发器的位置 |
className | string | - | 附加 CSS 类 |
children | ReactNode | - | 子内容 |
Autocomplete.Filter
| Prop | 类型 | 默认值 | 描述 |
|---|---|---|---|
filter | (text: string, input: string) => boolean | - | 自定义过滤函数 |
inputValue | string | - | 受控输入值 |
onInputChange | (value: string) => void | - | 输入值变化时的回调 |
children | ReactNode | - | 过滤内容(SearchField 与 ListBox) |
useFilter Hook
React Aria 的 useFilter hook 提供自动完成过滤函数。
import {useFilter} from "@heroui/react";
const {contains} = useFilter({sensitivity: "base"});
<Autocomplete.Filter filter={contains}>
<SearchField>...</SearchField>
<ListBox>...</ListBox>
</Autocomplete.Filter>Options:
| Option | 类型 | 默认值 | 描述 |
|---|---|---|---|
sensitivity | "base" | "accent" | "case" | "variant" | "base" | 匹配的 locale 敏感度 |
Returns:
| Function | 类型 | 描述 |
|---|---|---|
contains | (string: string, substring: string) => boolean | 判断字符串是否包含子串 |
startsWith | (string: string, substring: string) => boolean | 判断字符串是否以子串开头 |
endsWith | (string: string, substring: string) => boolean | 判断字符串是否以子串结尾 |
Render Props
使用 Autocomplete.Value 的 render 函数时,提供以下值:
| Prop | 类型 | 描述 |
|---|---|---|
defaultChildren | ReactNode | 默认渲染的值 |
isPlaceholder | boolean | 是否为占位符 |
state | SelectState | 自动完成的状态 |
selectedItems | Node[] | 当前选中项 |
无障碍
Autocomplete 组件实现带过滤的 ARIA select 模式,提供:
- 完整键盘导航支持
- 选择变化的屏幕阅读器播报
- 正确的焦点管理
- 禁用状态支持
- 带过滤的搜索功能
- HTML 表单集成
更多信息请参阅 React Aria Select 文档。





