ComboBox 组合框新
将文本输入与 ListBox 结合,用户可通过输入查询把选项列表过滤为匹配项
用法
import { ComboBox } from '@heroui/react';组件结构
import { ComboBox, Input, Label, Description, Header, ListBox, Separator } from '@heroui/react';
export default () => (
<ComboBox>
<Label />
<ComboBox.InputGroup>
<Input />
<ComboBox.Trigger />
</ComboBox.InputGroup>
{/* 展示已选中的值,主要用于多选 */}
<ComboBox.Value />
<Description />
<ComboBox.Popover>
<ListBox>
<ListBox.Item>
<Label />
<Description />
<ListBox.ItemIndicator />
</ListBox.Item>
<ListBox.Section>
<Header />
<ListBox.Item>
<Label />
</ListBox.Item>
</ListBox.Section>
</ListBox>
</ComboBox.Popover>
</ComboBox>
)示例
宽度充满
带描述
必填
禁用
含禁用选项
分组选项
受控组件
受控输入值
异步加载
默认选中项
允许自定义值
自定义指示器
自定义展示值
自定义过滤
渲染函数
菜单触发方式
使用 menuTrigger prop 控制 Popover 何时打开:
focus(默认):输入框获得焦点时打开 Popoverinput:用户编辑输入文本时打开 Popovermanual:仅当用户按下触发按钮或使用方向键时打开 Popover
表单值
使用 formValue 控制提交表单时提交选中项的 key 还是文本。默认值为 key。当 allowsCustomValue 为 true 时,始终提交文本。
校验行为
使用 validationBehavior 控制校验信息的展示方式:
native(默认):值为空或无效时阻止表单提交aria:实时显示错误,不阻止提交
自定义校验
使用 validate 在值无效时返回错误信息,有效时返回 true。
只读
使用 isReadOnly 将 ComboBox 设为只读。选中值可以获得焦点,但不能修改。
多选
设置 selectionMode="multiple" 以允许选择多个选项。在多选模式下,使用 ComboBox.Value 展示已选项,并同时给内部的 ListBox 传入 selectionMode="multiple"。选择通过 value / defaultValue(Key[])以及 onChange 回调来控制。
表面样式
在 Surface 内使用时,请使用 variant="secondary" 以应用适合 Surface 背景的低强调变体。
自定义样式
Tailwind CSS
全局 CSS
可使用 @layer components 指令自定义 ComboBox 组件类。
了解更多。
@layer components {
.combo-box {
@apply flex flex-col gap-1;
}
.combo-box__input-group {
@apply relative inline-flex items-center;
}
.combo-box__trigger {
@apply absolute right-0 text-muted;
}
.combo-box__popover {
@apply rounded-lg border border-border bg-surface p-2;
}
}样式参考
HeroUI 遵循 BEM 方法论,确保组件变体与状态可复用且易于自定义。
CSS 类
ComboBox 组件使用以下 CSS 类(查看源码样式):
基础类
.combo-box- ComboBox 根容器.combo-box__input-group- 输入框与触发按钮的容器.combo-box__value- 已选值的展示区域(用于多选).combo-box__trigger- 打开 Popover 的按钮.combo-box__popover- Popover 容器
状态类
.combo-box[data-invalid="true"]- 无效状态.combo-box[data-disabled="true"]- 禁用状态.combo-box__trigger[data-focus-visible="true"]- 触发器聚焦.combo-box__trigger[data-disabled="true"]- 触发器禁用.combo-box__trigger[data-open="true"]- 展开状态
交互状态
组件同时支持 CSS 伪类与 data 属性:
- Hover:触发器上
:hover或[data-hovered="true"] - Focus:触发器上
:focus-visible或[data-focus-visible="true"] - Disabled:ComboBox 上
:disabled或[data-disabled="true"] - Open:触发器上
[data-open="true"]
API 参考
ComboBox
| Prop | 类型 | 默认值 | 描述 |
|---|---|---|---|
inputValue | string | - | 当前输入值(受控) |
defaultInputValue | string | - | 默认输入值(非受控) |
onInputChange | (value: string) => void | - | 输入值变化时的回调 |
selectionMode | "single" | "multiple" | "single" | 启用单选还是多选 |
selectedKey | Key | null | - | 当前选中的 key(受控,单选) |
defaultSelectedKey | Key | null | - | 默认选中的 key(非受控,单选) |
onSelectionChange | (key: Key | null) => void | - | 选中变化时的回调(单选) |
value | Key | null | Key[] | - | 当前选中的 key(受控)。当 selectionMode="multiple" 时为 Key[] |
defaultValue | Key | null | Key[] | - | 初始选中的 key(非受控)。当 selectionMode="multiple" 时为 Key[] |
onChange | (value: Key | null | Key[]) => void | - | 选中变化时的回调 |
items | Iterable<T> | - | 在 ListBox 中展示的 items |
disabledKeys | Iterable<Key> | - | 禁用项的 key |
defaultFilter | (text: string, inputValue: string) => boolean | - | 用于过滤 items 的自定义过滤函数 |
isDisabled | boolean | - | 是否禁用 ComboBox |
isReadOnly | boolean | - | 输入是否可选中但不可由用户更改 |
isRequired | boolean | - | 是否必填 |
isInvalid | boolean | - | ComboBox 的值是否无效 |
validate | (value: ComboBoxValidationValue) => ValidationError | true | null | undefined | - | 若给定值无效则返回错误信息的函数。当 validationBehavior="native" 时,提交表单会向用户展示校验错误;实时校验请改用 isInvalid prop |
validationBehavior | "native" | "aria" | "native" | 使用原生 HTML 表单校验在值缺失或无效时阻止提交,还是通过 ARIA 将字段标记为必填或无效 |
name | string | - | 提交 HTML 表单时 input 的 name |
form | string | - | 要关联的 <form> 元素 id |
formValue | "text" | "key" | "key" | 在 HTML 表单提交时提交选中项的文本还是 key。当 allowsCustomValue 为 true 时该选项不适用,始终提交文本 |
autoComplete | string | - | 自动完成行为类型 |
autoFocus | boolean | - | 是否在挂载时自动聚焦 |
allowsCustomValue | boolean | - | 是否允许不在列表中的自定义值 |
allowsEmptyCollection | boolean | - | 是否允许空集合 |
menuTrigger | "focus" | "input" | "manual" | "focus" | 展示 ComboBox 菜单所需的交互 |
shouldFocusWrap | boolean | - | 键盘导航是否循环 |
fullWidth | boolean | false | ComboBox 是否占满容器宽度 |
variant | "primary" | "secondary" | "primary" | 视觉变体。primary 为默认带阴影样式;secondary 为低强调无阴影,适用于 Surface 内 |
className | string | - | 附加 CSS 类 |
children | ReactNode | RenderFunction | - | ComboBox 内容或 render 函数 |
render | DOMRenderFunction<keyof React.JSX.IntrinsicElements, ComboBoxRenderProps> | - | 使用自定义 render 函数覆盖默认 DOM 元素 |
ComboBox.InputGroup
| Prop | 类型 | 默认值 | 描述 |
|---|---|---|---|
className | string | - | 附加 CSS 类 |
children | ReactNode | - | InputGroup 内容 |
ComboBox.Value
渲染 ComboBox 已选中的值,若未选中任何值则渲染占位符。默认情况下,已选项以逗号分隔的列表形式渲染。可使用 render 函数自定义(例如以标签形式展示)。
| Prop | 类型 | 默认值 | 描述 |
|---|---|---|---|
placeholder | ReactNode | - | 未选中任何项时展示的值 |
className | string | (values: ComboBoxValueRenderProps) => string | - | 附加 CSS 类 |
children | ReactNode | (values: ComboBoxValueRenderProps) => ReactNode | - | 自定义已选值的 render 函数 |
ComboBox.Trigger
| Prop | 类型 | 默认值 | 描述 |
|---|---|---|---|
className | string | - | 附加 CSS 类 |
children | ReactNode | - | 自定义触发器内容 |
ComboBox.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" | 相对于触发器的 Popover 位置 |
className | string | - | 附加 CSS 类 |
children | ReactNode | - | 子内容 |
Render Props
对 ComboBox 使用 render 函数时,会传入以下值:
| Prop | 类型 | 描述 |
|---|---|---|
state | ComboBoxState | ComboBox 状态 |
inputValue | string | 当前输入值 |
selectedKey | Key | null | 当前选中的 key |
selectedItem | Node | null | 当前选中的 item |
无障碍
ComboBox 实现 ARIA ComboBox 模式,并提供:
- 完整键盘导航
- 选择与输入变化时的屏幕阅读器播报
- 合理的焦点管理
- 禁用状态支持
- 输入过滤(typeahead)式搜索
- 与 HTML 表单的集成
- 自定义值支持
更多信息见 React Aria ComboBox 文档。





