Autocomplete
A text field that suggests as you type, without ever refusing what you typed.
Anything can be typed here. The list only suggests.
Installation
npx shadcn@latest add https://qure-ui.qure.ai/r/autocomplete.jsonUsage
import {
Autocomplete, AutocompleteContent, AutocompleteEmpty,
AutocompleteInput, AutocompleteItem, AutocompleteList,
} from '@/components/ui/autocomplete'const terms = ['Ground-glass opacity', 'Consolidation', 'Cavitation']
<Autocomplete items={terms}>
<AutocompleteInput placeholder="Describe the finding" />
<AutocompleteContent>
<AutocompleteEmpty>No suggestion — the text is kept as typed.</AutocompleteEmpty>
<AutocompleteList>
{(term: string) => <AutocompleteItem key={term} value={term}>{term}</AutocompleteItem>}
</AutocompleteList>
</AutocompleteContent>
</Autocomplete>Autocomplete or combobox
They look identical and they are not the same control. The difference is what happens to text that matches nothing.
| Autocomplete | Combobox | |
|---|---|---|
| Free text | Kept | Discarded on close |
| Holds a selection | No | Yes |
| Row has a tick | No | Yes |
| Value | The string in the input | The chosen item |
An impression field, a search box and a "reason for study" box are autocompletes: the vocabulary helps, but a radiologist who needs to write something the list has never heard of must be able to. A protocol picker is a combobox: a protocol that is not in the list is a typo, not a new protocol.
If you find yourself reading the chosen item back out of an autocomplete, it was a combobox. Autocomplete's value is the text; there is no selected item to read.
Composition
<Autocomplete> {/* owns the text and the open state */}
<AutocompleteInputGroup> {/* optional; only when the field holds more than the input */}
<AutocompleteInput>
<AutocompleteClear>
</AutocompleteInputGroup>
<AutocompleteContent> {/* portal + positioner + popup */}
<AutocompleteStatus> {/* announced politely */}
<AutocompleteEmpty> {/* announced politely */}
<AutocompleteList>
<AutocompleteGroup>
<AutocompleteGroupLabel>
<AutocompleteCollection>
<AutocompleteItem>
</AutocompleteContent>
</Autocomplete>The input can stand on its own — it carries the field border itself — so the group is only worth adding when there is a search icon or a clear button to put beside it.
Completing inline
mode="both" filters the list and completes the input: the rest of the highlighted suggestion
appears after the caret as selected text, so the next keystroke overwrites it rather than
fighting it. Pair it with autoHighlight or there is nothing to complete from.
Use it where the vocabulary is closed and familiar — site names, scanner names. Avoid it in free prose, where a completion the writer did not ask for reads as the field arguing with them.
Suggestions that are not matches
mode="none" leaves the list static. These are recent searches, not results: filtering them
against the new query would make them vanish exactly when they stop matching the half-typed
thing, which is not the same as ceasing to be useful. openOnInputClick shows them on focus.
Groups
Grouped items are { value, items }, the same shape as Combobox. Stock phrases group well
because the reader is looking for a category first and a sentence second.
Modes
mode is the whole behaviour of the component in one prop.
| Mode | Filters the list | Completes the input |
|---|---|---|
list (default) | Yes | No |
both | Yes | Yes |
inline | No | Yes |
none | No | No |
Keyboard
Observed: typing opens and filters; ArrowDown moves into the list and loops back to the input past the end; Enter takes the highlighted suggestion into the input; Escape closes the list and leaves whatever was typed in place — it does not revert the field, which is the point of the control.
API Reference
Everything Base UI's Autocomplete accepts.
What we add on AutocompleteInput:
Prop
Type
On AutocompleteContent:
Prop
Type
On Autocomplete itself:
Prop
Type