Trivela UI

Autocomplete

A text input that suggests matching options as you type, with variant and color token support.

The only stateful component in the registry — it is marked 'use client', so importing it into a server component tree is fine, but the file itself cannot be rendered on the server. Because it draws its own list instead of using a native dropdown, the color tokens apply in every browser — unlike Select, whose open list is drawn by the OS.

Usage

autocomplete-demo.tsx
import { Autocomplete } from 'trivela-ui';

export function Example() {
  return (
    <Autocomplete
      options={['Next.js', 'Remix', 'Astro']}
      placeholder="Search framework…"
    />
  );
}

Examples

Basic

Pass plain strings and the component filters them as you type. Focus the field to see every option, or use ↑ ↓ and Enter.

Colors

The color token drives the highlighted option as well as the input focus ring. Open each one to compare.

Variants

The input reuses Input's variants, so an Autocomplete sits cleanly next to the rest of a form.

Separate value and label

Pass objects when the stored value differs from the text shown, and mark any option disabled. onSelect fires on commit and reports the value, not the label.

Controlled

Pass value and onValueChange to own the text yourself. onSelect fires only on commit — a click or Enter — not on every keystroke.

Typed: · Selected:

Custom filter

The default match is a case-insensitive substring. Pass filter to change it — here to a prefix match.

Empty state

When nothing matches, the list shows emptyMessage instead of collapsing — so the field never looks broken.

API Reference

PropTypeDefaultDescription
options(string | { value: string; label?: string; disabled?: boolean })[]Required. Strings are used as both value and label; label falls back to value.
value / onValueChangestring / (value: string) => voidControls the input text. Omit both to let the component own it.
onSelect(option: { value, label }) => voidFires on commit — click or Enter — not on every keystroke.
filter(option, query) => booleansubstring matchCase-insensitive substring match on the label by default.
emptyMessagestring'No results found.'Shown when no option matches the query.
variant'solid' | 'ghost' | 'outline' | 'subtle''solid'Style variant for the text input.
color'primary' | 'secondary' | 'success' | 'warning' | 'danger' | 'info' | 'neutral''primary'Color scale for the highlighted option and focus ring.
classNamestringMerged onto the input, not the wrapper.
...propsInputHTMLAttributes<HTMLInputElement>Forwarded to the input. value, defaultValue, onChange and onSelect are owned by the component.