Active Foundation · Example
A person found by a simulated server search
A person found by a simulated server searchSimulationA server imitated in your browser: shows the interaction, not a working server integration.
Value: null
Full source examples/ui/async-combobox.tsx
// apps/docs/examples/ui/async-combobox.tsx'use client';
import {useState} from 'react';
import { AsyncCombobox, type AsyncComboboxOption,} from '@workspace/active-ui/components/composed/async-combobox';import { Field, FieldDescription, FieldLabel,} from '@workspace/active-ui/components/primitives/field';
// Fictitious people. The "server" below is a simulation in the browser.const PEOPLE = [ 'Ada Jansen', 'Bram de Vries', 'Chloé Martin', 'Daan Bakker', 'Eva Smit', 'Fatima El Amrani', 'Gijs Visser', 'Hanna Meijer',].map((name, index) => ({value: `person-${index + 1}`, label: name}));
/** A search that takes 600 ms, honours the signal, and fails on "error". */function simulatedSearch(query: string, signal: AbortSignal) { return new Promise<readonly AsyncComboboxOption[]>((resolve, reject) => { const timer = window.setTimeout(() => { if (query.toLowerCase().includes('error')) { reject(new Error('Simulated failure')); return; } const needle = query.toLowerCase(); resolve( PEOPLE.filter((person) => person.label.toLowerCase().includes(needle)), ); }, 600); signal.addEventListener('abort', () => { window.clearTimeout(timer); reject(new DOMException('Aborted', 'AbortError')); }); });}
/** * A choice from a list the server searches. Type two letters to search; * typing "error" shows the failed state. The value is the whole option, since * the chosen person is usually not in the next result. */export default function AsyncComboboxExample() { const [person, setPerson] = useState<AsyncComboboxOption | null>(null); return ( <Field className="w-full max-w-xs"> <FieldLabel htmlFor="contact-person">Contact person</FieldLabel> <AsyncCombobox id="contact-person" value={person} onValueChange={setPerson} onSearch={simulatedSearch} placeholder="Choose a person" searchLabel="Search people" searchPlaceholder="Type a name…" typeToSearchText="Type at least two letters." loadingText="Searching…" emptyText="Nobody found." errorText="The search failed. Try again." aria-describedby="contact-person-value" /> <FieldDescription id="contact-person-value"> Value: <code>{person ? person.value : 'null'}</code> </FieldDescription> </Field> );}