Autocomplete
Features
- Can be controlled or uncontrolled.
- Offers 2 positioning modes.
- Supports items, labels, groups of items.
- Focus is fully managed.
- Full keyboard navigation.
- Supports custom placeholder.
- Supports Right to Left direction.
- Free-form text input — value is the typed text, not a selection.
Installation
Install the component from your command line.
$ npm add reka-uiAnatomy
Import all parts and piece them together.
<script setup lang="ts">
import {
AutocompleteAnchor,
AutocompleteArrow,
AutocompleteCancel,
AutocompleteContent,
AutocompleteEmpty,
AutocompleteGroup,
AutocompleteInput,
AutocompleteItem,
AutocompleteLabel,
AutocompletePortal,
AutocompleteRoot,
AutocompleteSeparator,
AutocompleteTrigger,
AutocompleteViewport,
} from 'reka-ui'
</script>
<template>
<AutocompleteRoot>
<AutocompleteAnchor>
<AutocompleteInput />
<AutocompleteTrigger />
<AutocompleteCancel />
</AutocompleteAnchor>
<AutocompletePortal>
<AutocompleteContent>
<AutocompleteViewport>
<AutocompleteEmpty />
<AutocompleteItem />
<AutocompleteSeparator />
<AutocompleteGroup>
<AutocompleteLabel />
<AutocompleteItem />
</AutocompleteGroup>
</AutocompleteViewport>
<AutocompleteArrow />
</AutocompleteContent>
</AutocompletePortal>
</AutocompleteRoot>
</template>Autocomplete vs. Combobox
The Autocomplete component is similar to the Combobox but with a key difference:
| Autocomplete | Combobox | |
|---|---|---|
modelValue | The input text (string) | The selected item (AcceptableValue) |
| Free-form text | Yes — any text is valid | No — must select from the list |
multiple | Not supported | Supported |
| Input on blur | Retains typed text by default | Resets to selected value by default |
| Item selection | Fills the input with the item's text value | Sets modelValue to the item's value |
Use Autocomplete when the user should be able to type anything with optional suggestions. Use Combobox when the user must pick from a predefined set of options.
API Reference
Root
Contains all the parts of an Autocomplete.
| Prop | Default | Type |
|---|---|---|
as | 'div' | AsTag | ComponentThe element or component this component should render as. Can be overwritten by |
asChild | booleanChange the default rendered element for the one passed as a child, merging their props and behavior. Read our Composition guide for more details. | |
defaultOpen | booleanThe open state of the autocomplete when it is initially rendered. Use when you do not need to control its open state. | |
defaultValue | stringThe value of the autocomplete when initially rendered. Use when you do not need to control the state. | |
dir | 'ltr' | 'rtl'The reading direction of the autocomplete when applicable. | |
disabled | booleanWhen | |
highlightOnHover | true | booleanWhen |
ignoreFilter | booleanWhen | |
modelValue | stringThe controlled value of the Autocomplete (the input text). Can be bound with | |
name | stringThe name of the field. Submitted with its owning form as part of a name/value pair. | |
open | booleanThe controlled open state of the Autocomplete. Can be bound with | |
openOnClick | false | booleanWhether to open the autocomplete when the input is clicked |
openOnFocus | false | booleanWhether to open the autocomplete when the input is focused |
required | booleanWhen | |
resetSearchTermOnBlur | false | booleanWhether to reset the searchTerm when the Autocomplete input blurred |
| Emit | Payload |
|---|---|
highlight | [payload: { ref: HTMLElement; value: string; }]Event handler when highlighted element changes. |
update:modelValue | [value: string]Event handler called when the value changes. |
update:open | [value: boolean]Event handler called when the open state of the autocomplete changes. |
| Slots (default) | Payload |
|---|---|
open | booleanCurrent open state |
modelValue | stringCurrent active value |
Anchor
Used as an anchor if you set AutocompleteContent's position to popper.
| Prop | Default | Type |
|---|---|---|
as | 'div' | AsTag | ComponentThe element or component this component should render as. Can be overwritten by |
asChild | booleanChange the default rendered element for the one passed as a child, merging their props and behavior. Read our Composition guide for more details. | |
reference | ReferenceElementThe reference (or anchor) element that is being referred to for positioning. If not provided will use the current component as anchor. |
Input
The input component to search through the autocomplete items. Typing updates the modelValue directly.
| Prop | Default | Type |
|---|---|---|
as | 'input' | AsTag | ComponentThe element or component this component should render as. Can be overwritten by |
asChild | booleanChange the default rendered element for the one passed as a child, merging their props and behavior. Read our Composition guide for more details. | |
autoFocus | booleanFocus on element when mounted. | |
disabled | booleanWhen | |
modelValue | stringThe controlled value of the filter. Can be binded with v-model. |
| Emit | Payload |
|---|---|
update:modelValue | [string]Event handler called when the value changes. |
Trigger
The button that toggles the Autocomplete Content.
| Prop | Default | Type |
|---|---|---|
as | 'button' | AsTag | ComponentThe element or component this component should render as. Can be overwritten by |
asChild | booleanChange the default rendered element for the one passed as a child, merging their props and behavior. Read our Composition guide for more details. | |
disabled | booleanWhen |
| Data Attribute | Value |
|---|---|
[data-state] | "open" | "closed" |
[data-disabled] | Present when disabled |
Cancel
The button that clears the input text and resets the value.
| Prop | Default | Type |
|---|---|---|
as | 'button' | AsTag | ComponentThe element or component this component should render as. Can be overwritten by |
asChild | booleanChange the default rendered element for the one passed as a child, merging their props and behavior. Read our Composition guide for more details. |
Empty
Shown when none of the items match the query.
| Prop | Default | Type |
|---|---|---|
as | 'div' | AsTag | ComponentThe element or component this component should render as. Can be overwritten by |
asChild | booleanChange the default rendered element for the one passed as a child, merging their props and behavior. Read our Composition guide for more details. |
Portal
When used, portals the content part into the body.
You need to set position="popper" for AutocompleteContent to make sure the position was automatically computed similar to Popover or DropdownMenu.
| Prop | Default | Type |
|---|---|---|
defer | booleanDefer the resolving of a Teleport target until other parts of the application have mounted (requires Vue 3.5.0+) | |
disabled | booleanDisable teleport and render the component inline | |
forceMount | booleanUsed to force mounting when more control is needed. Useful when controlling animation with Vue animation libraries. | |
to | string | HTMLElementVue native teleport component prop |
Content
The component that pops out when the autocomplete is open.
| Prop | Default | Type |
|---|---|---|
align | 'start' | 'center' | 'end'The preferred alignment against the trigger. May change when collisions occur. | |
alignFlip | booleanFlip alignment when colliding with boundary.
May only occur when | |
alignOffset | numberAn offset in pixels from the | |
arrowPadding | numberThe padding between the arrow and the edges of the content. If your content has border-radius, this will prevent it from overflowing the corners. | |
as | 'div' | AsTag | ComponentThe element or component this component should render as. Can be overwritten by |
asChild | booleanChange the default rendered element for the one passed as a child, merging their props and behavior. Read our Composition guide for more details. | |
avoidCollisions | booleanWhen | |
bodyLock | booleanThe document.body will be lock, and scrolling will be disabled. | |
collisionBoundary | Element | (Element | null)[] | nullThe 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 | number | Partial<Record<'top' | 'right' | 'bottom' | 'left', number>>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 }. | |
disableOutsidePointerEvents | booleanWhen | |
disableUpdateOnLayoutShift | booleanWhether to disable the update position for the content when the layout shifted. | |
forceMount | booleanUsed to force mounting when more control is needed. Useful when controlling animation with Vue animation libraries. | |
hideShiftedArrow | booleanWhen | |
hideWhenDetached | booleanWhether to hide the content when the trigger becomes fully occluded. | |
hideWhenEmpty | booleanWhen | |
position | 'inline' | 'popper'The positioning mode to use, | |
positionStrategy | 'fixed' | 'absolute'The type of CSS position property to use. | |
prioritizePosition | booleanForce content to be position within the viewport. Might overlap the reference element, which may not be desired. | |
reference | ReferenceElementThe 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. | |
side | 'top' | 'right' | 'bottom' | 'left'The preferred side of the trigger to render against when open. Will be reversed when collisions occur and avoidCollisions is enabled. | |
sideFlip | booleanFlip to the opposite side when colliding with boundary. | |
sideOffset | numberThe distance in pixels from the trigger. | |
sticky | 'partial' | 'always'The sticky behavior on the align axis. | |
updatePositionStrategy | 'always' | 'optimized'Strategy to update the position of the floating element on every animation frame. |
| Emit | Payload |
|---|---|
escapeKeyDown | [event: KeyboardEvent]Event handler called when the escape key is down. Can be prevented. |
focusOutside | [event: FocusOutsideEvent]Event handler called when the focus moves outside of the |
interactOutside | [event: PointerDownOutsideEvent | FocusOutsideEvent]Event handler called when an interaction happens outside the |
pointerDownOutside | [event: PointerDownOutsideEvent]Event handler called when a |
| Data Attribute | Value |
|---|---|
[data-state] | "open" | "closed" |
[data-side] | "left" | "right" | "bottom" | "top" |
[data-align] | "start" | "end" | "center" |
[data-empty] | Present when there are no items matching the filter |
| CSS Variable | Description |
|---|---|
--reka-combobox-content-transform-origin | The transform-origin computed from the content and arrow positions/offsets. Only present when position="popper". |
--reka-combobox-content-available-width | The remaining width between the trigger and the boundary edge. Only present when position="popper". |
--reka-combobox-content-available-height | The remaining height between the trigger and the boundary edge. Only present when position="popper". |
--reka-combobox-trigger-width | The width of the trigger. Only present when position="popper". |
--reka-combobox-trigger-height | The height of the trigger. Only present when position="popper". |
Viewport
The scrolling viewport that contains all of the items.
| Prop | Default | Type |
|---|---|---|
as | 'div' | AsTag | ComponentThe element or component this component should render as. Can be overwritten by |
asChild | booleanChange the default rendered element for the one passed as a child, merging their props and behavior. Read our Composition guide for more details. | |
nonce | stringWill add |
Item
The component that contains the autocomplete items. When selected, the item's string value fills the input.
| Prop | Default | Type |
|---|---|---|
as | 'div' | AsTag | ComponentThe element or component this component should render as. Can be overwritten by |
asChild | booleanChange the default rendered element for the one passed as a child, merging their props and behavior. Read our Composition guide for more details. | |
disabled | booleanWhen | |
textValue | stringA string representation of the item contents. If the children are not plain text, then the | |
value* | AcceptableValueThe value given as data when submitted with a |
| Emit | Payload |
|---|---|
select | [event: SelectEvent<AcceptableValue>]Event handler called when the selecting item. |
| Data Attribute | Value |
|---|---|
[data-state] | "checked" | "unchecked" |
[data-highlighted] | Present when highlighted |
[data-disabled] | Present when disabled |
Group
Used to group multiple items. Use in conjunction with AutocompleteLabel to ensure good accessibility via automatic labelling.
| Prop | Default | Type |
|---|---|---|
as | 'div' | AsTag | ComponentThe element or component this component should render as. Can be overwritten by |
asChild | booleanChange the default rendered element for the one passed as a child, merging their props and behavior. Read our Composition guide for more details. |
Label
Used to render the label of a group. It won't be focusable using arrow keys.
| Prop | Default | Type |
|---|---|---|
as | 'div' | AsTag | ComponentThe element or component this component should render as. Can be overwritten by |
asChild | booleanChange the default rendered element for the one passed as a child, merging their props and behavior. Read our Composition guide for more details. | |
for | string |
Separator
Used to visually separate items in the Autocomplete.
| Prop | Default | Type |
|---|---|---|
as | 'div' | AsTag | ComponentThe element or component this component should render as. Can be overwritten by |
asChild | booleanChange the default rendered element for the one passed as a child, merging their props and behavior. Read our Composition guide for more details. |
Arrow
An optional arrow element to render alongside the content. This can be used to help visually link the trigger with the AutocompleteContent. Must be rendered inside AutocompleteContent. Only available when position is set to popper.
| Prop | Default | Type |
|---|---|---|
as | 'svg' | AsTag | ComponentThe element or component this component should render as. Can be overwritten by |
asChild | booleanChange the default rendered element for the one passed as a child, merging their props and behavior. Read our Composition guide for more details. | |
height | 5 | numberThe height of the arrow in pixels. |
rounded | booleanWhen | |
width | 10 | numberThe width of the arrow in pixels. |
Virtualizer
Virtual container to achieve list virtualization.
See the virtualization guide for more general info on virtualization.
| Prop | Default | Type |
|---|---|---|
estimateSize | number | ((index: number) => number)Estimated size (in px) of each item | |
options* | AcceptableValue[]List of items | |
overscan | numberNumber of items rendered outside the visible area | |
textContent | ((option: AcceptableValue) => string)Text content for each item to achieve type-ahead feature |
| Slots (default) | Payload |
|---|---|
option | null | string | number | bigint | Record<string, any> |
virtualizer | Virtualizer<HTMLElement, Element> |
virtualItem | VirtualItem |
Examples
Basic usage
The modelValue is a string that reflects whatever the user types. Selecting an item fills the input with that item's text.
<script setup lang="ts">
import { AutocompleteContent, AutocompleteInput, AutocompleteItem, AutocompletePortal, AutocompleteRoot } from 'reka-ui'
import { ref } from 'vue'
const searchText = ref('')
const fruits = ['Apple', 'Banana', 'Orange', 'Grapes', 'Pineapple']
</script>
<template>
<AutocompleteRoot v-model="searchText">
<AutocompleteInput placeholder="Type a fruit..." />
<AutocompletePortal>
<AutocompleteContent>
<AutocompleteItem
v-for="fruit in fruits"
:key="fruit"
:value="fruit"
>
{{ fruit }}
</AutocompleteItem>
</AutocompleteContent>
</AutocompletePortal>
</AutocompleteRoot>
</template>Hide menu when empty
Use the hideWhenEmpty prop on AutocompleteContent to hide the menu when no items match the filter.
<template>
<AutocompleteRoot v-model="searchText">
<AutocompleteInput placeholder="Type a fruit..." />
<AutocompletePortal>
<AutocompleteContent hide-when-empty>
<AutocompleteItem
v-for="fruit in fruits"
:key="fruit"
:value="fruit"
>
{{ fruit }}
</AutocompleteItem>
</AutocompleteContent>
</AutocompletePortal>
</AutocompleteRoot>
</template>With form submission
The Autocomplete value is submitted as a regular text field in forms.
<script setup lang="ts">
import { AutocompleteContent, AutocompleteInput, AutocompleteItem, AutocompletePortal, AutocompleteRoot } from 'reka-ui'
import { ref } from 'vue'
const query = ref('')
const cities = ['New York', 'Los Angeles', 'Chicago', 'Houston', 'Phoenix']
</script>
<template>
<form>
<AutocompleteRoot v-model="query" name="city">
<AutocompleteInput placeholder="Enter a city..." />
<AutocompletePortal>
<AutocompleteContent>
<AutocompleteItem
v-for="city in cities"
:key="city"
:value="city"
>
{{ city }}
</AutocompleteItem>
</AutocompleteContent>
</AutocompletePortal>
</AutocompleteRoot>
</form>
</template>Accessibility
Adheres to the Combobox WAI-ARIA design pattern.
Keyboard Interactions
| Key | Description |
|---|---|
Enter | When focus is on AutocompleteItem, selects the focused item and fills the input with its value. |
ArrowDown | When focus is on AutocompleteInput, opens the autocomplete content. When focus is on an item, moves focus to the next item. |
ArrowUp | When focus is on AutocompleteInput, opens the autocomplete content. When focus is on an item, moves focus to the previous item. |
Esc | Closes the autocomplete content and returns focus to AutocompleteInput. |
