- Components
Combobox
A text field that filters a list as you type and picks one option.
npx shadcn add @klarhimmel/combobox @klarhimmel/inputWhen to use
Use for
Long lists people can name: countries, staff, products. They type, the list narrows.
Not for
Fewer than seven options. Use Select. Free text with suggestions. Use Input.
Pairs with
Field, forms.
Preview
- Denmark
- Estonia
- Finland
- Germany
- Iceland
- Latvia
- Lithuania
- Netherlands
- Norway
- Poland
- Sweden
- United Kingdom
Start typing to narrow the list.
Nothing chosen yet.
combobox.tsx
import { Theme } from '@/components/klarhimmel/theme/style';
import { Combobox } from '@/components/klarhimmel/ui/combobox';
import { Field } from '@/components/klarhimmel/ui/input';
export default function Example() {
return (
<Theme theme="brand">
<Field label="Country">
{(p) => (
<Combobox
{...p}
options={[
{ value: 'dk', label: 'Denmark' },
{ value: 'fi', label: 'Finland' },
{ value: 'no', label: 'Norway' },
{ value: 'se', label: 'Sweden' },
]}
placeholder="Search countries"
/>
)}
</Field>
</Theme>
);
}Install
Import
import { Combobox } from '@/components/klarhimmel/ui/combobox';- Lands in
- components/klarhimmel/ui/combobox.tsx, plus cn() and the theme item if they are missing. Import theme.css after Tailwind.
- Render in
- Render it inside <Theme>, once near the root of your app. Tokens and fonts are scoped to it, so outside it the component is unstyled.
Examples
States
- Astrid Nyberg
- Bo Lindgren
- Cecilia Åberg
- David Ek
- Elin Sjöberg
- Fredrik Lund
- Greta Wahl
- Hugo Mård
David is on leave, so he cannot be picked.
- Astrid Nyberg
- Bo Lindgren
- Cecilia Åberg
- David Ek
- Elin Sjöberg
- Fredrik Lund
- Greta Wahl
- Hugo Mård
Pick a reviewer.
import { Combobox } from '@/components/klarhimmel/ui/combobox'; import { Field } from '@/components/klarhimmel/ui/input'; const staff = ['Astrid Nyberg', 'Bo Lindgren', 'Cecilia Åberg', 'David Ek', 'Elin Sjöberg', 'Fredrik Lund', 'Greta Wahl', 'Hugo Mård'].map((n) => ({ value: n, label: n, disabled: n === 'David Ek' })); export default function ComboboxStates() { return ( <div className="grid w-[min(40rem,calc(100cqw-3rem))] min-h-72 content-start gap-6 @md:grid-cols-2"> <Field label="Assign to" hint="David is on leave, so he cannot be picked.">{(p) => <Combobox {...p} options={staff} defaultValue="Greta Wahl" emptyText="Nobody by that name" />}</Field> <Field label="Reviewer" error="Pick a reviewer.">{(p) => <Combobox {...p} options={staff} placeholder="Type a name" />}</Field> </div> ); }Long
- Arvika
- Borås
- Eskilstuna
- Falun
- Gävle
- Halmstad
- Jönköping
- Karlstad
- Linköping
- Malmö
- Norrköping
- Örebro
- Piteå
- Skellefteå
- Sundsvall
- Uppsala
- Västerås
- Växjö
- Ystad
- Åre
- Östersund
Scroll the list, or type a few letters.
import { Combobox } from '@/components/klarhimmel/ui/combobox'; import { Field } from '@/components/klarhimmel/ui/input'; const towns = ['Arvika', 'Borås', 'Eskilstuna', 'Falun', 'Gävle', 'Halmstad', 'Jönköping', 'Karlstad', 'Linköping', 'Malmö', 'Norrköping', 'Örebro', 'Piteå', 'Skellefteå', 'Sundsvall', 'Uppsala', 'Västerås', 'Växjö', 'Ystad', 'Åre', 'Östersund'].map((t) => ({ value: t, label: t })); export default function ComboboxLong() { return ( <div className="flex min-h-80 w-[min(24rem,calc(100cqw-3rem))] flex-col"> <Field label="Nearest town" hint="Scroll the list, or type a few letters.">{(p) => <Combobox {...p} options={towns} placeholder="Type a town" />}</Field> </div> ); }
API reference
| Prop | Type | Default | Description |
|---|---|---|---|
options | { value: string; label: string; disabled?: boolean }[] | - | Required. Matching is case-insensitive and anywhere in the label. |
value / defaultValue / onValueChange | string / (value: string) => void | - | Controlled or uncontrolled state. An empty string means nothing chosen. |
placeholder / emptyText | string | - / 'No matches' | Placeholder; the message when nothing matches. |
name | string | - | Submits the chosen value with a form (a hidden input). |
invalid / disabled | boolean | false | Error styling; switches it off. |
className | string | - | Extra classes, merged after the component's own. |
Accessibility
| Key | Does |
|---|---|
Type | Opens the list and filters it; the first match is highlighted |
Down / Up | Opens the list, or moves the highlight |
Enter | Chooses the highlighted option |
Escape | Closes and restores the chosen text; again, clears the field |
Home / End / Left / Right | Move the caret in the text, as in any field |
Tab | Leaves the field; unmatched text is replaced by the chosen label |
The WAI-ARIA combobox with list autocomplete. The number of matches is announced as you type.
Accessibility