import { Autocomplete } from "@photon-ai/kumo-solid";
/** 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 value={item}>{item}</Autocomplete.Item>
)}
</Autocomplete.List>
</Autocomplete.Content>
</Autocomplete>
);
}Installation
Barrel
import { Autocomplete } from "@photon-ai/kumo-solid";Granular
import { Autocomplete } from "@photon-ai/kumo-solid/components/autocomplete";When to use
Use Autocomplete when the input value can be free-form text and suggestions
are optional hints. Use Combobox instead when the selected value must come
from the predefined list.
Controlled
Pass value and onValueChange for controlled usage.
import { createSignal } from "solid-js";
import { Autocomplete } from "@photon-ai/kumo-solid";
/** Controlled autocomplete with value and onValueChange. */
export function AutocompleteControlledDemo() {
const [value, setValue] = createSignal("");
return (
<div class="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 value={item}>{item}</Autocomplete.Item>
)}
</Autocomplete.List>
</Autocomplete.Content>
</Autocomplete>
{value() && (
<p class="text-sm text-kumo-subtle">
Value: <span class="font-medium text-kumo-default">{value()}</span>
</p>
)}
</div>
);
}With Field
Add label, description, and required to enable the built-in Field wrapper.
Start typing to filter languages
import { Autocomplete } from "@photon-ai/kumo-solid";
import { languages, Language } from "./data/languages";
/** Autocomplete with label, description, and Field wrapper. */
export function AutocompleteWithFieldDemo() {
const filterUtils = Autocomplete.useFilter();
const filter = (item: Language, query: string) =>
filterUtils.contains(item.label, query);
return (
<div class="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 value={item}>
{item.emoji} {item.label}
</Autocomplete.Item>
)}
</Autocomplete.List>
</Autocomplete.Content>
</Autocomplete>
</div>
);
}Error State
Display validation errors with the error prop.
import { Autocomplete } from "@photon-ai/kumo-solid";
/** Autocomplete with error state via the Field wrapper. */
export function AutocompleteErrorDemo() {
const filterUtils = Autocomplete.useFilter();
const filter = (item: Country, query: string) =>
filterUtils.contains(item.label, query);
return (
<div class="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 value={item}>{item.label}</Autocomplete.Item>
)}
</Autocomplete.List>
</Autocomplete.Content>
</Autocomplete>
</div>
);
}Grouped
Group items into categories using Autocomplete.Group and Autocomplete.GroupLabel.
import { Autocomplete } from "@photon-ai/kumo-solid";
/** 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 items={group.items}>
<Autocomplete.GroupLabel>{group.value}</Autocomplete.GroupLabel>
<Autocomplete.Collection>
{(item: ServerLocation) => (
<Autocomplete.Item value={item}>
{item.label}
</Autocomplete.Item>
)}
</Autocomplete.Collection>
</Autocomplete.Group>
)}
</Autocomplete.List>
</Autocomplete.Content>
</Autocomplete>
);
}Sizes
The size prop on Autocomplete.InputGroup supports four variants matching the
Input component: xs, sm, base (default), and lg.
import { Autocomplete } from "@photon-ai/kumo-solid";
/** Demonstrates the four size variants: xs, sm, base, and lg. */
export function AutocompleteSizesDemo() {
return (
<div class="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 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 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 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 value={item}>{item}</Autocomplete.Item>
)}
</Autocomplete.List>
</Autocomplete.Content>
</Autocomplete>
</div>
);
}Filtering
Filtering is case- and accent-insensitive by default, powered by
Intl.Collator under the hood. For string items, no custom filter is
needed.
When filtering on a property of object items, use
Autocomplete.useFilter() to preserve the built-in accent-insensitive
matching:
function LanguagePicker() {
const filterUtils = Autocomplete.useFilter();
const filter = (item: Language, query: string) =>
filterUtils.contains(item.label, query);
return (
<Autocomplete items={languages} filter={filter}>
{/* ... */}
</Autocomplete>
);
}To disable filtering entirely (e.g. when results come from a server), pass
filter={null}:
<Autocomplete items={results} filter={null}>
...
</Autocomplete>API Reference
Autocomplete
Root component. Wraps all sub-components and manages state.
| 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 | JSX.Element | - | Autocomplete content (input group, popup content) |
| className | string | - | Additional CSS classes |
| label | JSX.Element | - | Label content (enables Field wrapper) |
| required | boolean | - | Whether the field is required |
| labelTooltip | JSX.Element | - | Tooltip content to display next to the label |
| description | JSX.Element | - | Helper text displayed below the field |
| error | string | object | - | Error message or validation error object |
Autocomplete.InputGroup
Self-contained input wrapper that renders the text input, clear button, and dropdown trigger together.
| Prop | Type | Default |
|---|---|---|
| className | string | - |
| size | KumoAutocompleteSize | - |
| placeholder | string | - |
Autocomplete.Content
Dropdown popup container. Wraps Portal, Positioner, and Popup.
| Prop | Type | Default |
|---|---|---|
| children | JSX.Element | - |
| className | string | - |
| align | AutocompleteBase.Positioner.Props["align"] | - |
| alignOffset | AutocompleteBase.Positioner.Props["alignOffset"] | - |
| side | AutocompleteBase.Positioner.Props["side"] | - |
| sideOffset | AutocompleteBase.Positioner.Props["sideOffset"] | - |
Autocomplete.Item
Individual suggestion item in the list.
| Prop | Type | Default |
|---|
No component-specific props. Accepts standard HTML attributes.
Additional Sub-components
Autocomplete.List— scrollable list container with render propAutocomplete.Group— groups items under a headingAutocomplete.GroupLabel— heading label for a groupAutocomplete.Collection— item container within a groupAutocomplete.Separator— horizontal divider between items