Autocomplete
Overview
An autocomplete that filters suggestion items from text input and quickly fills the input with a selected result. It opens as you type, fuzzy-matches options with Fuse, and supports grouping, a clearable input, and a data-driven compact API. Use it when users should type keywords to get suggestions over free text; when options come from a fixed list, prefer SSelect; when options come from a known set that benefits from type-to-filter, SCombobox is the closer sibling.
Usage
Features
- 🔍 Type-to-open filtering backed by Fuse fuzzy search (
threshold: 0.3, matchinglabel/value/keywords/groupLabel) - ⌨️ Full keyboard navigation — ArrowDown/Up/Home/End open and move, Enter/Space select, typeahead, Escape close
- 🗂 Grouping with group labels, separators, and empty states (no-match / no-data)
- 🧹 Clearable input (
clearable→clearLabel/resetModelValueOnClear) - 🎛
openOnFocus/openOnClickdual open strategy with controlledv-model:open - 📊 Data-driven
AutocompleteCompactAPI —items(options uselabel/valuefields) + grouping - ♿ WAI-ARIA combobox pattern —
role="combobox"/listbox/option,aria-activedescendant, axe-clean when open - 🎨 17 recipe slots and 7 size variants via
autocompleteVariants
Demos
Basic
Value: —
Grouped
Custom Styling
API
Aria Layer
14Autocomplete<T>
Props
| Prop | Type | Default | Description |
|---|---|---|---|
class | ClassValue | — | Root class. |
size | ThemeSize | — | Visual size of the component. |
ui | Partial<AutocompleteUi> | — | Per-slot class overrides for the component. |
modelValue | string | — | The controlled value of the autocomplete input. |
defaultValue | string | — | The initial value of the autocomplete input. |
items | AutocompleteOptionData<T>[] | — | Items rendered by the component. |
placeholder | string | — | Placeholder. |
clearable | boolean | — | Whether clearable. |
clearLabel | string | — | Clear label. |
emptyLabel | string | — | Empty label. |
fuseOptions | UseFuseOptions<T> | — | Fuse options. |
anchorProps | AutocompleteAnchorProps | — | Properties forwarded to the anchor element. |
inputProps | AutocompleteInputProps | — | Properties forwarded to the input element. |
triggerProps | AutocompleteTriggerProps | — | Properties forwarded to the trigger element. |
portalProps | PortalProps | — | Properties forwarded to the portal element. |
contentProps | AutocompleteContentProps | — | Properties forwarded to the content element. |
viewportProps | AutocompleteViewportProps | — | Properties forwarded to the viewport element. |
groupProps | AutocompleteGroupProps | — | Properties forwarded to the group element. |
groupLabelProps | AutocompleteGroupLabelProps | — | Properties forwarded to the group label element. |
itemProps | Omit<AutocompleteItemProps, 'disabled' | 'value'> | — | Properties forwarded to the item element. |
itemIndicatorProps | AutocompleteItemIndicatorProps | — | Properties forwarded to the item indicator element. |
separatorProps | AutocompleteSeparatorProps | — | Properties forwarded to the separator element. |
open | boolean | — | The controlled open state of the autocomplete popup. |
defaultOpen | boolean | — | The open state of the autocomplete popup when initially rendered. |
disabled | boolean | — | When `true`, prevents the user from interacting with autocomplete. |
dir | Direction | — | The reading direction of the autocomplete when applicable. |
name | string | — | The name of the field. Submitted with its owning form as part of a name/value pair. |
highlightOnHover | boolean | — | When `true`, hover over item will trigger highlight. |
openOnFocus | boolean | — | Whether to open the autocomplete when the input is focused. |
openOnClick | boolean | — | Whether to open the autocomplete when the input is clicked. |
resetModelValueOnClear | boolean | — | When `true`, clearing the search term also resets `modelValue` to an empty string. |
required | boolean | — | When `true`, indicates that the user must set the value before the owning form can be submitted. |
Emits
| Emit Name | Parameters | Description |
|---|---|---|
update:modelValue | string | Emitted when the model value changes. |
update:open | boolean | Emitted when the open state changes. |
highlight | AutocompleteHighlightPayload | undefined | Emitted when highlight occurs. |
select | T | Emitted when select occurs. |
Slots
| Slot Name | Parameters | Description |
|---|---|---|
input-leading | — | Custom content for the input leading slot. |
input-trailing | — | Custom content for the input trailing slot. |
trigger-icon | — | Custom content for the trigger icon slot. |
empty | — | Custom content for the empty slot. |
group-label | { item: AutocompleteGroupOptionData<T> | Extract<T, { items: T[]; }>; } | Custom content for the group label slot. |
item-leading | { item: T; } | Custom content for the item leading slot. |
item-text | { item: T; } | Custom content for the item text slot. |
item-trailing | { item: T; } | Custom content for the item trailing slot. |
item-indicator | { item: T; } | Custom content for the item indicator slot. |
AutocompleteAnchor
Props
| Prop | Type | Default | Description |
|---|---|---|---|
reference | ReferenceElement | — | — |
asChild | boolean | — | Change the default rendered element for the one passed as a child, merging their props and behavior. |
as | AsTag | Component | 'div' | The element or component this component should render as. Can be overwrite by `asChild` |
AutocompleteCompact<T>
Props
| Prop | Type | Default | Description |
|---|---|---|---|
modelValue | string | — | The controlled value of the autocomplete input. |
defaultValue | string | — | The initial value of the autocomplete input. |
items | AutocompleteOptionData<T>[] | — | Items rendered by the component. |
placeholder | string | — | Placeholder. |
clearable | boolean | — | Whether clearable. |
clearLabel | string | — | Clear label. |
emptyLabel | string | — | Empty label. |
fuseOptions | UseFuseOptions<T> | — | Fuse options. |
anchorProps | AutocompleteAnchorProps | — | Properties forwarded to the anchor element. |
inputProps | AutocompleteInputProps | — | Properties forwarded to the input element. |
triggerProps | AutocompleteTriggerProps | — | Properties forwarded to the trigger element. |
portalProps | PortalProps | — | Properties forwarded to the portal element. |
contentProps | AutocompleteContentProps | — | Properties forwarded to the content element. |
viewportProps | AutocompleteViewportProps | — | Properties forwarded to the viewport element. |
groupProps | AutocompleteGroupProps | — | Properties forwarded to the group element. |
groupLabelProps | AutocompleteGroupLabelProps | — | Properties forwarded to the group label element. |
itemProps | Omit<AutocompleteItemProps, 'disabled' | 'value'> | — | Properties forwarded to the item element. |
itemIndicatorProps | AutocompleteItemIndicatorProps | — | Properties forwarded to the item indicator element. |
separatorProps | AutocompleteSeparatorProps | — | Properties forwarded to the separator element. |
open | boolean | — | The controlled open state of the autocomplete popup. |
defaultOpen | boolean | — | The open state of the autocomplete popup when initially rendered. |
disabled | boolean | — | When `true`, prevents the user from interacting with autocomplete. |
dir | Direction | — | The reading direction of the autocomplete when applicable. |
name | string | — | The name of the field. Submitted with its owning form as part of a name/value pair. |
highlightOnHover | boolean | — | When `true`, hover over item will trigger highlight. |
openOnFocus | boolean | — | Whether to open the autocomplete when the input is focused. |
openOnClick | boolean | — | Whether to open the autocomplete when the input is clicked. |
resetModelValueOnClear | boolean | — | When `true`, clearing the search term also resets `modelValue` to an empty string. |
required | boolean | — | When `true`, indicates that the user must set the value before the owning form can be submitted. |
Emits
| Emit Name | Parameters | Description |
|---|---|---|
update:modelValue | string | Emitted when the model value changes. |
update:open | boolean | Emitted when the open state changes. |
highlight | AutocompleteHighlightPayload | undefined | Emitted when highlight occurs. |
select | T | Emitted when select occurs. |
Slots
| Slot Name | Parameters | Description |
|---|---|---|
input-leading | — | Custom content for the input leading slot. |
input-trailing | — | Custom content for the input trailing slot. |
trigger-icon | — | Custom content for the trigger icon slot. |
empty | — | Custom content for the empty slot. |
group-label | { item: Extract<AutocompleteOptionData<T>, { items: T[]; }>; } | Custom content for the group label slot. |
item-leading | { item: T; } | Custom content for the item leading slot. |
item-text | { item: T; } | Custom content for the item text slot. |
item-trailing | { item: T; } | Custom content for the item trailing slot. |
item-indicator | { item: T; } | Custom content for the item indicator slot. |
AutocompleteContent
Props
| Prop | Type | Default | Description |
|---|---|---|---|
position | 'inline' | 'popper' | — | Position. |
bodyLock | boolean | — | Whether body lock. |
hideWhenEmpty | boolean | — | Whether hide when empty. |
popupProps | PopperPositioningPopupProps | — | Properties forwarded to the popup element. |
open | boolean | true | Whether the floating layer is open. Drives the positioning lifecycle (`isPositioned`
resets when open flips); the positioning primitive itself has no open state, so
consumers wire their own open state here. |
placement | Placement | undefined | The placement of the floating element.
If used, it will override the `side` and `align` props. |
side | Side | 'bottom' | The preferred side of the anchor to render against when open. Will be reversed when collisions occur and
avoidCollisions is enabled. |
sideOffset | number | 0 | The distance in pixels from the anchor. |
sideFlip | boolean | true | Flip to the opposite side when colliding with boundary. |
align | Align | 'center' | The preferred alignment against the anchor. May change when collisions occur. |
alignOffset | number | 0 | An offset in pixels from the `start` or `end` alignment options. |
alignFlip | boolean | true | Flip alignment when colliding with boundary.
May only occur when `prioritizePosition` is true. |
avoidCollisions | boolean | true | When `true`, overrides the side and align preferences to prevent collisions with boundary edges. |
collisionBoundary | Element | (Element | null)[] | null | [ ] | The element used as the collision boundary. By default this is the viewport, though you can provide additional
element(s) to be included in this check. |
collisionPadding | Padding | 0 | The distance in pixels from the boundary edges where collision detection should occur. Accepts a number (same for
all sides), or a partial padding object, for example: { top: 20, left: 20 }. |
arrowPadding | number | 0 | The padding between the arrow and the edges of the content. If your content has border-radius, this will prevent it
from overflowing the corners. |
hideShiftedArrow | boolean | false | When `true`, hides the arrow when it cannot be centered
to the reference element. |
sticky | 'partial' | 'always' | 'partial' | The sticky behavior on the align axis. `partial` will keep the content in the boundary as long as the anchor is at
least partially in the boundary whilst "always" will keep the content in the boundary regardless. |
hideWhenDetached | boolean | false | Whether to hide the content when the anchor becomes fully occluded. |
positionStrategy | 'fixed' | 'absolute' | 'fixed' | The type of CSS position property to use. |
updatePositionStrategy | 'always' | 'optimized' | 'optimized' | Strategy to update the position of the floating element on every animation frame. |
disableUpdateOnLayoutShift | boolean | false | Whether to disable the update position for the content when the layout shifted. |
prioritizePosition | boolean | false | Force content to be position within the viewport. Might overlap the reference element, which may not be desired. |
reference | ReferenceElement | — | The custom element or virtual element that will be set as the reference to position the floating element. If
provided, it will replace the default anchor element. |
trapFocus | boolean | false | When `true`, focus cannot escape the content via keyboard, pointer, or a programmatic focus. |
disableOutsidePointerEvents | boolean | — | When `true`, hover/focus/click interactions will be disabled on elements outside the `DismissableLayer`. Users will
need to click twice on outside elements to interact with them: once to close the `DismissableLayer`, and again to
trigger the element. |
forceMount | boolean | — | Used to force mounting when more control is needed.
Useful when controlling animation with Vue animation libraries. |
Emits
| Emit Name | Parameters | Description |
|---|---|---|
escapeKeyDown | KeyboardEvent | Event handler called when the escape key is down. Can be prevented. |
pointerDownOutside | PointerDownOutsideEvent | Event handler called when a `pointerdown` event happens outside of the `DismissableLayer`. Can be prevented. |
focusOutside | FocusOutsideEvent | Event handler called when the focus moves outside of the `DismissableLayer`. Can be prevented. |
interactOutside | PointerDownOutsideEvent | FocusOutsideEvent | Event handler called when an interaction happens outside the `DismissableLayer`. Specifically, when a `pointerdown`
event happens outside or focus moves outside of it. Can be prevented. |
openAutoFocus | Event | Event handler called when auto-focusing on open. Can be prevented. |
closeAutoFocus | Event | Event handler called when auto-focusing on close. Can be prevented. |
placed | — | Event handler called when the positioner is placed |
AutocompleteGroup
AutocompleteGroupLabel
AutocompleteInput
Props
| Prop | Type | Default | Description |
|---|---|---|---|
inputRef | ((el: HTMLInputElement) => void) | — | Input ref. |
controlProps | InputControlProps | — | Properties forwarded to the control element. |
disabled | boolean | — | When `true`, prevents the user from interacting with the input. |
id | string | — | Id of the input element |
placeholder | string | — | The placeholder of the input |
type | InputTypeHTMLAttribute | — | The type of the input element. |
autofocus | boolean | — | When `true`, the input is auto-focused. |
name | string | — | The name of the field. Submitted with its owning form as part of a name/value pair. |
required | boolean | — | When `true`, indicates that the user must set the value before the owning form can be submitted. |
readonly | boolean | — | When `true`, the input is read-only. |
rootProps | BaseProps | — | Properties forwarded to the root element |
autocomplete | 'search' | 'name' | 'email' | 'tel' | 'url' | 'on' | 'off' | 'username' | 'current-password' | 'new-password' | 'one-time-code' | 'given-name' | 'family-name' | 'organization' | 'street-address' | 'address-level2' | 'postal-code' | 'country' | 'cc-name' | 'cc-number' | 'cc-exp' | 'cc-csc' | 'transaction-amount' | — | The autocomplete attribute of the input.
Supports the HTML autofill tokens (including password-manager values such as
`current-password` / `new-password`), in addition to the `on` / `off` switches. |
maxlength | number | — | The maximum number of characters allowed in the input |
minlength | number | — | The minimum number of characters allowed in the input |
pattern | string | — | The pattern attribute of the input |
AutocompleteItem
Props
| Prop | Type | Default | Description |
|---|---|---|---|
textValue | string | — | Text value. |
value | string | — | The value given as data when submitted with a `name`. |
disabled | boolean | — | When `true`, prevents the user from interacting with the item. |
asChild | boolean | — | Change the default rendered element for the one passed as a child, merging their props and behavior. |
as | AsTag | Component | 'div' | The element or component this component should render as. Can be overwrite by `asChild` |
Emits
| Emit Name | Parameters | Description |
|---|---|---|
select | SelectEvent<string> | Event handler called when the selecting item. <br> It can be prevented by calling `event.preventDefault`. |
AutocompleteItemIndicator
Props
| Prop | Type | Default | Description |
|---|---|---|---|
asChild | boolean | — | Change the default rendered element for the one passed as a child, merging their props and behavior. |
as | AsTag | Component | 'div' | The element or component this component should render as. Can be overwrite by `asChild` |
AutocompletePortal
AutocompleteRoot
Props
| Prop | Type | Default | Description |
|---|---|---|---|
modelValue | string | — | The controlled value of the autocomplete input. |
defaultValue | string | — | The value of the autocomplete input when initially rendered. |
open | boolean | — | The controlled open state of the autocomplete popup. |
defaultOpen | boolean | — | The open state of the autocomplete popup when initially rendered. |
dir | Direction | — | The reading direction of the autocomplete when applicable. |
disabled | boolean | — | When `true`, prevents the user from interacting with autocomplete. |
highlightOnHover | boolean | — | When `true`, hover over item will trigger highlight. |
openOnFocus | boolean | — | Whether to open the autocomplete when the input is focused. |
openOnClick | boolean | — | Whether to open the autocomplete when the input is clicked. |
resetModelValueOnClear | boolean | — | When `true`, clearing the search term also resets `modelValue` to an empty string. |
name | string | — | The name of the field. Submitted with its owning form as part of a name/value pair. |
required | boolean | — | When `true`, indicates that the user must set the value before the owning form can be submitted. |
Emits
| Emit Name | Parameters | Description |
|---|---|---|
update:modelValue | string | Emitted when the model value changes. |
update:open | boolean | Emitted when the open state changes. |
highlight | AutocompleteHighlightPayload | undefined | Emitted when highlight occurs. |
AutocompleteSeparator
Props
| Prop | Type | Default | Description |
|---|---|---|---|
asChild | boolean | — | Change the default rendered element for the one passed as a child, merging their props and behavior. |
as | AsTag | Component | 'div' | The element or component this component should render as. Can be overwrite by `asChild` |
AutocompleteTrigger
Props
| Prop | Type | Default | Description |
|---|---|---|---|
disabled | boolean | — | Whether the component is disabled. |
asChild | boolean | — | Change the default rendered element for the one passed as a child, merging their props and behavior. |
as | AsTag | Component | 'div' | The element or component this component should render as. Can be overwrite by `asChild` |
AutocompleteViewport
Props
| Prop | Type | Default | Description |
|---|---|---|---|
nonce | string | — | Nonce. |
Notes
Architecture and benchmark differences
VeanUI builds autocomplete by reusing the combobox component family (Anchor/Content/Item/Viewport/Trigger/Empty/Cancel) over the listbox base plus Popper positioning. AutocompleteRoot disables combobox’s built-in filtering (ignoreFilter) and delegates matching to the compact layer’s useFuse, so autocomplete and combobox share the same interaction kernel and differ only in filter and display strategy. The scv() recipe autocompleteVariants declares 17 slots and 7 size variants.
| Capability | VeanUI | reka-ui Combobox | Algolia Autocomplete | Ant Design AutoComplete |
|---|---|---|---|---|
| Aria/styled split | ✅ | ✅ | — | — |
| Type-to-filter + fuzzy match | ✅ | — | ✅ | ✅ |
| combobox/listbox roles | ✅ | ✅ | ✅ | ✅ |
| Keyboard nav + typeahead | ✅ | ✅ | ✅ | ✅ |
| Grouping + group labels | ✅ | ✅ | — | — |
openOnFocus / openOnClick | ✅ | — | ✅ | ✅ |
| Clear button + empty state | ✅ | ✅ | — | ✅ |
| Data-driven Compact API | ✅ | — | — | — |
| axe-clean (open state) | ✅ | — | — | — |
Cautions
- Filtering happens client-side with Fuse; for remote suggestions, pass pre-filtered
itemsor debounce the input yourself. - The popup stays open when focus moves to the clear button (the blur-enclosure check covers the whole anchor area) and closes only when focus leaves the component — this was a fixed regression, so do not restore trigger-only containment.
- When the root is
disabled, every item is unselectable, including items that declare their owndisabled(unifiedrootDisabled || item.disabledguard). - The viewport (
role="listbox") exposes a localizedaria-labelby default; override it viaviewportProps['aria-label'].
FAQ
How do I show suggestions without typing?
Use openOnFocus to open the popup when the input receives focus, and openOnClick to open when the input is clicked.
How do I tune how fuzzy the matching is?
Pass fuseOptions to tune the Fuse search — for example, raise threshold for looser matches or use keys to restrict which fields participate.
What is the difference between SAutocomplete, SCombobox, and SSelect?
SAutocomplete fuzzy-matches suggestions over free text (Fuse); SCombobox type-to-filters a known option list; SSelect is trigger-driven with typeahead only and no text input.
How do I clear the input and reset the model value?
Pass clearable. resetModelValueOnClear decides whether clearing also emits an empty modelValue or only resets the search term.