Autocomplete
A text field that suggests values as you type and keeps whatever is typed, suggestion or not.
ui.autocomplete
components/ui/autocomplete.tsxUse case
Use it for a text value where suggestions help but are not the only answer: the city on a client's address, a job title, a supplier that may be new. The value is the input's text (a string), so a new entry is kept as typed; picking a suggestion only fills the text in.
Use it when
- Free text with suggestions (a city, a street, a tag that may be new)
- The value saved is the text, not a record's id
- Speeding up the typing of common values
Use something else when
- The value must be an existing record (a client, a product): Combobox
- Searching the whole tool for pages, records and actions: Command bar
- Filtering the list on the page as you type: Search field
- A short fixed list: Select
Examples
Code
Import
import { Autocomplete, AutocompleteEmpty, AutocompleteInput, AutocompleteItem, AutocompleteList, AutocompletePopup } from "@/components/ui/autocomplete"Usage
const CITIES = ["Montréal", "Laval", "Longueuil", "Québec", "Gatineau", "Sherbrooke"].map((c) => ({ value: c, label: c }))
<Autocomplete items={CITIES}>
<AutocompleteInput name="city" placeholder="City" aria-label="City" />
<AutocompletePopup>
<AutocompleteEmpty>Keep typing, any city works.</AutocompleteEmpty>
<AutocompleteList>
{(item: (typeof CITIES)[number]) => (
<AutocompleteItem key={item.value} value={item}>
{item.label}
</AutocompleteItem>
)}
</AutocompleteList>
</AutocompletePopup>
</Autocomplete>Rules
- The value is a string (`value`, `onValueChange`), never limited to the suggestions.
- `AutocompleteEmpty` says the typed text is still fine ("Keep typing, any city works."), not that it is wrong.
- Name the input: a `FieldLabel` in a form, or `aria-label`; pass `name` so a form submits the text.
- Keep `AutocompleteList`: it scrolls inside a `ScrollArea` that fades at its edges.
- The list glides to its new height as you type, its top fixed (useGlide on the popup, built in).