import { Autocomplete } from "@cloudflare/kumo";
/** Basic autocomplete with a flat list of strings. */
export function AutocompleteDemo() {
return (
<Autocomplete items={fruits}>
<Autocomplete.InputGroup placeholder="Search fruits…" />
<Autocomplete.Content>
<Autocomplete.List>
{(item: string) => (
<Autocomplete.Item key={item} value={item}>
{item}
</Autocomplete.Item>
)}
</Autocomplete.List>
</Autocomplete.Content>
</Autocomplete>
);
}安装
批量导入
import { Autocomplete } from "@cloudflare/kumo";按需导入
import { Autocomplete } from "@cloudflare/kumo/components/autocomplete";适用场景
当输入值可以是自由文本、建议仅为可选提示时,使用 Autocomplete。当选中的值必须来自预定义列表时,改用 Combobox。
受控
传入 value 和 onValueChange 以实现受控用法。
import { useState } from "react";
import { Autocomplete } from "@cloudflare/kumo";
/** Controlled autocomplete with value and onValueChange. */
export function AutocompleteControlledDemo() {
const [value, setValue] = useState("");
return (
<div className="flex w-80 flex-col gap-3">
<Autocomplete
items={fruits}
value={value}
onValueChange={(v) => setValue(v)}
>
<Autocomplete.InputGroup placeholder="Type a fruit…" />
<Autocomplete.Content>
<Autocomplete.List>
{(item: string) => (
<Autocomplete.Item key={item} value={item}>
{item}
</Autocomplete.Item>
)}
</Autocomplete.List>
</Autocomplete.Content>
</Autocomplete>
{value && (
<p className="text-sm text-kumo-subtle">
Value: <span className="font-medium text-kumo-default">{value}</span>
</p>
)}
</div>
);
}配合 Field
添加 label、description 和 required 以启用内置的 Field 包装器。
Start typing to filter languages
import { useCallback } from "react";
import { Autocomplete } from "@cloudflare/kumo";
import { languages, Language } from "./data/languages";
/** Autocomplete with label, description, and Field wrapper. */
export function AutocompleteWithFieldDemo() {
const { contains } = Autocomplete.useFilter();
const filter = useCallback(
(item: Language, query: string) => contains(item.label, query),
[contains],
);
return (
<div className="w-80">
<Autocomplete
items={languages}
label="Language"
description="Start typing to filter languages"
filter={filter}
>
<Autocomplete.InputGroup placeholder="Search a language…" />
<Autocomplete.Content>
<Autocomplete.List>
{(item: Language) => (
<Autocomplete.Item key={item.value} value={item}>
{item.emoji} {item.label}
</Autocomplete.Item>
)}
</Autocomplete.List>
</Autocomplete.Content>
</Autocomplete>
</div>
);
}错误状态
通过 error 属性展示校验错误。
Please enter a valid country
import { useCallback } from "react";
import { Autocomplete } from "@cloudflare/kumo";
/** Autocomplete with error state via the Field wrapper. */
export function AutocompleteErrorDemo() {
const { contains } = Autocomplete.useFilter();
const filter = useCallback(
(item: Country, query: string) => contains(item.label, query),
[contains],
);
return (
<div className="w-80">
<Autocomplete
items={countries}
label="Country"
error={{ message: "Please enter a valid country", match: true }}
filter={filter}
>
<Autocomplete.InputGroup placeholder="Search countries…" />
<Autocomplete.Content>
<Autocomplete.List>
{(item: Country) => (
<Autocomplete.Item key={item.code} value={item}>
{item.label}
</Autocomplete.Item>
)}
</Autocomplete.List>
</Autocomplete.Content>
</Autocomplete>
</div>
);
}分组
使用 Autocomplete.Group 和 Autocomplete.GroupLabel 将项目按类别分组。
import { Autocomplete } from "@cloudflare/kumo";
/** Autocomplete with grouped items using Group and GroupLabel. */
export function AutocompleteGroupedDemo() {
return (
<Autocomplete items={servers}>
<Autocomplete.InputGroup placeholder="Select region…" />
<Autocomplete.Content>
<Autocomplete.List>
{(group: ServerGroup) => (
<Autocomplete.Group key={group.value} items={group.items}>
<Autocomplete.GroupLabel>{group.value}</Autocomplete.GroupLabel>
<Autocomplete.Collection>
{(item: ServerLocation) => (
<Autocomplete.Item key={item.value} value={item}>
{item.label}
</Autocomplete.Item>
)}
</Autocomplete.Collection>
</Autocomplete.Group>
)}
</Autocomplete.List>
</Autocomplete.Content>
</Autocomplete>
);
}尺寸
Autocomplete.InputGroup 上的 size 属性支持与 Input 组件一致的四种变体:xs、sm、base(默认)和 lg。
import { Autocomplete } from "@cloudflare/kumo";
/** Demonstrates the four size variants: xs, sm, base, and lg. */
export function AutocompleteSizesDemo() {
return (
<div className="flex flex-wrap items-center gap-4">
<Autocomplete items={fruits.slice(0, 10)}>
<Autocomplete.InputGroup size="xs" placeholder="xs" />
<Autocomplete.Content>
<Autocomplete.List>
{(item: string) => (
<Autocomplete.Item key={item} value={item}>
{item}
</Autocomplete.Item>
)}
</Autocomplete.List>
</Autocomplete.Content>
</Autocomplete>
<Autocomplete items={fruits.slice(0, 10)}>
<Autocomplete.InputGroup size="sm" placeholder="sm" />
<Autocomplete.Content>
<Autocomplete.List>
{(item: string) => (
<Autocomplete.Item key={item} value={item}>
{item}
</Autocomplete.Item>
)}
</Autocomplete.List>
</Autocomplete.Content>
</Autocomplete>
<Autocomplete items={fruits.slice(0, 10)}>
<Autocomplete.InputGroup size="base" placeholder="base (default)" />
<Autocomplete.Content>
<Autocomplete.List>
{(item: string) => (
<Autocomplete.Item key={item} value={item}>
{item}
</Autocomplete.Item>
)}
</Autocomplete.List>
</Autocomplete.Content>
</Autocomplete>
<Autocomplete items={fruits.slice(0, 10)}>
<Autocomplete.InputGroup size="lg" placeholder="lg" />
<Autocomplete.Content>
<Autocomplete.List>
{(item: string) => (
<Autocomplete.Item key={item} value={item}>
{item}
</Autocomplete.Item>
)}
</Autocomplete.List>
</Autocomplete.Content>
</Autocomplete>
</div>
);
}过滤
默认情况下过滤不区分大小写和重音符号,底层由 Intl.Collator 实现。对于字符串项,无需自定义 filter。
当需要对对象项的某个属性进行过滤时,使用 Autocomplete.useFilter() 以保留内置的不区分重音符号的匹配行为:
function LanguagePicker() {
const { contains } = Autocomplete.useFilter();
const filter = useCallback(
(item: Language, query: string) => contains(item.label, query),
[contains],
);
return (
<Autocomplete items={languages} filter={filter}>
{/* ... */}
</Autocomplete>
);
}若要完全禁用过滤(例如结果来自服务器时),传入 filter={null}:
<Autocomplete items={results} filter={null}>
...
</Autocomplete>API 参考
Autocomplete
根组件。包装所有子组件并管理状态。
| Prop | Type | Default | Description |
|---|---|---|---|
| items* | unknown[] | - | Array of items to display in the dropdown |
| value | string | number | string[] | - | The controlled input value |
| open | boolean | - | Whether the popup is open (controlled) |
| children | ReactNode | - | Autocomplete content (input group, popup content) |
| className | string | - | Additional CSS classes |
| label | ReactNode | - | Label content (enables Field wrapper) |
| required | boolean | - | Whether the field is required |
| labelTooltip | ReactNode | - | Tooltip content to display next to the label |
| description | ReactNode | - | Helper text displayed below the field |
| error | string | object | - | Error message or validation error object |
Autocomplete.InputGroup
自包含的输入包装器,将文本输入框、清除按钮和下拉触发器渲染在一起。
| Prop | Type | Default |
|---|---|---|
| className | string | - |
| size | KumoAutocompleteSize | - |
| placeholder | string | - |
Autocomplete.Content
下拉弹层容器。包装 Portal、Positioner 和 Popup。
| Prop | Type | Default |
|---|---|---|
| children | ReactNode | - |
| className | string | - |
| align | AutocompleteBase.Positioner.Props["align"] | - |
| alignOffset | AutocompleteBase.Positioner.Props["alignOffset"] | - |
| side | AutocompleteBase.Positioner.Props["side"] | - |
| sideOffset | AutocompleteBase.Positioner.Props["sideOffset"] | - |
Autocomplete.Item
列表中的单个建议项。
| Prop | Type | Default |
|---|
No component-specific props. Accepts standard HTML attributes.
其他子组件
Autocomplete.List— 带 render prop 的可滚动列表容器Autocomplete.Group— 将项目归并到某个标题下Autocomplete.GroupLabel— 分组的标题标签Autocomplete.Collection— 组内的项目容器Autocomplete.Separator— 项目之间的水平分隔线