Skip to content

Autocomplete

Async search input with suggestions dropdown.

Also known as: typeahead, search input, async search, combobox, suggestion input

View in Storybook

When to use

  • Search with async suggestions from API. For static option lists, use Select.
  • For multiple selections, use MultiSelect or Tags.

Import

tsx
import { Autocomplete } from '@vacano/ui'

Usage

tsx
import { Autocomplete, AutocompleteValue, AutocompleteSuggestion } from '@vacano/ui'

const [value, setValue] = useState<AutocompleteValue>({ value: '', image_url: null })

const handleSearch = async (query: string): Promise<AutocompleteSuggestion[]> => {
  const response = await fetch(`/api/search?q=${query}`)
  return response.json() // [{ id, value, image_url }]
}

<Autocomplete
  label="Search"
  placeholder="Type to search..."
  value={value}
  onChange={setValue}
  onSearch={handleSearch}
/>

With Images

Suggestions can include images (avatars, icons, etc.):

tsx
const handleSearch = async (query: string) => {
  return [
    { id: '1', value: 'John Doe', image_url: 'https://example.com/avatar.jpg' },
    { id: '2', value: 'Jane Smith', image_url: null },
  ]
}

<Autocomplete
  label="Select User"
  onSearch={handleSearch}
  value={value}
  onChange={setValue}
/>

Variants

tsx
<Autocomplete variant="normal" label="Normal" onSearch={handleSearch} />
<Autocomplete variant="error" label="Error" onSearch={handleSearch} />

Sizes

tsx
<Autocomplete size="default" label="Default Size" onSearch={handleSearch} />
<Autocomplete size="compact" label="Compact Size" onSearch={handleSearch} />

Custom Debounce

tsx
<Autocomplete
  debounceMs={500}
  label="Slow Search"
  onSearch={handleSearch}
/>

Minimum Characters

tsx
<Autocomplete
  minChars={3}
  label="Search (min 3 chars)"
  onSearch={handleSearch}
/>

Custom No Results Message

For internationalization:

tsx
<Autocomplete
  noResultsMessage="Ничего не найдено"
  label="Поиск"
  onSearch={handleSearch}
/>

Portal rendering

When the Autocomplete is placed inside a container with overflow: hidden or overflow: auto, the dropdown will be clipped. Use portalRenderNode to render the dropdown via a portal so it escapes the container:

tsx
<Autocomplete
  label="City"
  onSearch={handleSearch}
  value={value}
  onChange={setValue}
  portalRenderNode={document.body}
/>

The dropdown automatically tracks the input position on scroll and resize when rendered in a portal.

Full Width

tsx
<Autocomplete fullWidth label="Full Width" onSearch={handleSearch} />

With Message

tsx
<Autocomplete label="User" variant="error" onSearch={handleSearch} message="User not found" />
<Autocomplete label="Search" onSearch={handleSearch} message="Start typing to search" />

Disabled

tsx
<Autocomplete
  disabled
  label="Disabled"
  value={{ value: 'Selected value', image_url: null }}
  onSearch={handleSearch}
/>

Props

PropTypeDefaultDescription
onSearch(query: string) => Promise<AutocompleteSuggestion[]>requiredAsync search function
onChange(value: AutocompleteValue) => void-Called on value change
valueAutocompleteValue-Current value
debounceMsnumber300Debounce delay in ms
minCharsnumber1Min characters to trigger search
noResultsMessagestring'No results found'Empty state message
labelstring-Label text
variant'normal' | 'error''normal'Visual variant
size'compact' | 'default''default'Input size
fullWidthbooleanfalseFull width input
messagestring-Message text below input (error, hint)
portalRenderNodeHTMLElement | null-Portal render node for dropdown (for overflow hidden containers). When set, dropdown is rendered via createPortal with fixed positioning.
disabledbooleanfalseDisabled state
classNamestring-CSS class name for the root element
classnamesAutocompleteClassNames-Custom class names for inner elements
refRef<HTMLInputElement>-Ref to the underlying input element
data-test-idstring-Test identifier attribute

All standard HTML input attributes are also supported (except className, size, onChange, and value which are controlled by the component).

Types

tsx
type AutocompleteSuggestion = {
  id: string
  value: string
  image_url: string | null
}

type AutocompleteValue = {
  value: string
  image_url: string | null
}

ClassNames

KeyDescription
inputInput element
labelLabel element
dropdownDropdown container
itemSuggestion item

Released under the MIT License.