Combobox
since v8.4.0Searchable single/multi value selector wrapping react-aria (ADR-0006). See
{@link ComboboxProps}.
Install
Add the package and import the component.
pnpm add @hey-mike/tungstenpnpm add @hey-mike/tungstenimport { Combobox } from '@hey-mike/tungsten';import { Combobox } from '@hey-mike/tungsten';Preview
Same fixtures used by the visual-regression suite.
Usage
apps/docs/app/snapshots/combobox/page.tsx
'use client';
import { Combobox } from '@hey-mike/tungsten';
import { VariantGrid } from '../_components/VariantGrid';
const FRUITS = [
{ id: 'apple', label: 'Apple' },
{ id: 'banana', label: 'Banana' },
{ id: 'cherry', label: 'Cherry' },
{ id: 'date', label: 'Date' },
];
export default function ComboboxSnapshot() {
return (
<VariantGrid
title="Combobox"
variants={[
{
label: 'empty',
node: (
<div className="w-64">
<Combobox label="Fruit" options={FRUITS} placeholder="Search fruit…" />
</div>
),
},
{
label: 'single (selected)',
node: (
<div className="w-64">
<Combobox label="Fruit" options={FRUITS} defaultSelectedKey="cherry" />
</div>
),
},
{
label: 'multi (chips)',
node: (
<div className="w-72">
<Combobox
mode="multiple"
label="Fruit"
options={FRUITS}
defaultSelectedKeys={['apple', 'cherry']}
placeholder="Add fruit…"
/>
</div>
),
},
]}
/>
);
}
'use client';
import { Combobox } from '@hey-mike/tungsten';
import { VariantGrid } from '../_components/VariantGrid';
const FRUITS = [
{ id: 'apple', label: 'Apple' },
{ id: 'banana', label: 'Banana' },
{ id: 'cherry', label: 'Cherry' },
{ id: 'date', label: 'Date' },
];
export default function ComboboxSnapshot() {
return (
<VariantGrid
title="Combobox"
variants={[
{
label: 'empty',
node: (
<div className="w-64">
<Combobox label="Fruit" options={FRUITS} placeholder="Search fruit…" />
</div>
),
},
{
label: 'single (selected)',
node: (
<div className="w-64">
<Combobox label="Fruit" options={FRUITS} defaultSelectedKey="cherry" />
</div>
),
},
{
label: 'multi (chips)',
node: (
<div className="w-72">
<Combobox
mode="multiple"
label="Fruit"
options={FRUITS}
defaultSelectedKeys={['apple', 'cherry']}
placeholder="Add fruit…"
/>
</div>
),
},
]}
/>
);
}
Props
Surface specific to <Combobox />.
| Prop | Type | Default | Description |
|---|---|---|---|
| mode | "single" | "multiple" | — | — |
| selectedKey | string | null | — | Controlled selected option id. Pair with onSelectionChange. |
| defaultSelectedKey | string | null | — | Uncontrolled initial selection. |
| onSelectionChange | ((id: string | null) => void) | ((ids: string[]) => void) | — | Fires when the selection changes (or clears → null). Fires with the full selected-id array on every add/remove. |
| options* | ComboboxOption[] | — | The full option list (already filtered if shouldFilter={false}). |
| inputValue | string | — | Controlled input text. Pair with onInputChange. |
| onInputChange | ((value: string) => void) | — | Fires on every keystroke — the hook for server-side/async filtering. |
| shouldFilter | boolean | — | Filter options client-side by the query (default). Set false for server-side. |
| isLoading | boolean | — | Show a loading row in the listbox (async in-flight). |
| error | string | — | Error message shown in the listbox when option loading failed. |
| emptyMessage | string | — | Message when there are zero options. |
| label | string | — | Accessible name for the input when not inside a FormField. |
| placeholder | string | — | Placeholder shown in the empty input. |
| isDisabled | boolean | — | Disable the control. |
| isRequired | boolean | — | Mark required (also read from FieldContext). |
| className | string | — | Class on the input. |
| aria-label | string | — | — |
| selectedKeys | string[] | — | Controlled selected ids. Pair with onSelectionChange. |
| defaultSelectedKeys | string[] | — | Uncontrolled initial selection. |
| maxSelections | number | — | Cap the number of selections; further picks are blocked once reached. |
Used in recipes
Compositions from the /recipes reference that use this component.
- →
Async option loading
A Combobox driven by useAsyncOptions: debounced server-side search with loading / empty states. shouldFilter is off so the server owns filtering.
- →
Searchable single-select
A Combobox that filters a static option list as you type and selects one value. The searchable alternative to Select for longer lists.
- →
Multi-select with chips in a FormField
A multi-select Combobox composed inside FormField. Selected tags render as removable chips; Backspace removes the last. Shows the FieldContext boundary.