Combobox
Kildekode på GitHub · Les som Markdown
Combobox er en søkbar nedtrekksmeny som kombinerer et tekstfelt med en filtrerbar liste. Ideell for tilfeller der brukeren må velge blant mange alternativer, for eksempel byer, ansatte eller produkter. Bygget på cmdk for fuzzy-søk og Radix UI Popover for posisjonering.
Importering
import {
Combobox,
ComboboxItem,
ComboboxGroup,
ComboboxSeparator,
} from "@kilden/designsystem";Grunnleggende bruk
function ComboboxDemo() { const [value, setValue] = React.useState(""); return ( <Combobox value={value} onValueChange={setValue} placeholder="Velg frukt..." className="w-[240px]"> <ComboboxItem value="eple">Eple</ComboboxItem> <ComboboxItem value="banan">Banan</ComboboxItem> <ComboboxItem value="appelsin">Appelsin</ComboboxItem> <ComboboxItem value="jordbær">Jordbær</ComboboxItem> <ComboboxItem value="mango">Mango</ComboboxItem> </Combobox> ); }
Med grupper
Bruk ComboboxGroup og ComboboxSeparator for å organisere alternativer.
function GroupedComboboxDemo() { const [value, setValue] = React.useState(""); return ( <Combobox value={value} onValueChange={setValue} placeholder="Velg mat..." className="w-[240px]"> <ComboboxGroup heading="Frukt"> <ComboboxItem value="eple">Eple</ComboboxItem> <ComboboxItem value="banan">Banan</ComboboxItem> <ComboboxItem value="appelsin">Appelsin</ComboboxItem> </ComboboxGroup> <ComboboxSeparator /> <ComboboxGroup heading="Grønnsaker"> <ComboboxItem value="gulrot">Gulrot</ComboboxItem> <ComboboxItem value="brokkoli">Brokkoli</ComboboxItem> <ComboboxItem value="spinat">Spinat</ComboboxItem> </ComboboxGroup> </Combobox> ); }
Asynkront søk
For datadrevne lister kan du deaktivere innebygd filtrering med shouldFilter={false} og styre resultatene selv via onSearchChange.
function AsyncComboboxDemo() { const [value, setValue] = React.useState(""); const [results, setResults] = React.useState([]); const [loading, setLoading] = React.useState(false); const allItems = [ { id: "oslo", name: "Oslo" }, { id: "bergen", name: "Bergen" }, { id: "trondheim", name: "Trondheim" }, { id: "stavanger", name: "Stavanger" }, { id: "tromsø", name: "Tromsø" }, { id: "drammen", name: "Drammen" }, { id: "kristiansand", name: "Kristiansand" }, ]; function handleSearch(search) { setLoading(true); // Simuler API-kall setTimeout(() => { setResults( search ? allItems.filter((item) => item.name.toLowerCase().includes(search.toLowerCase()) ) : allItems ); setLoading(false); }, 300); } return ( <Combobox value={value} onValueChange={setValue} placeholder="Søk etter by..." onSearchChange={handleSearch} loading={loading} shouldFilter={false} emptyMessage="Ingen byer funnet." className="w-[240px]" > {results.map((item) => ( <ComboboxItem key={item.id} value={item.id}> {item.name} </ComboboxItem> ))} </Combobox> ); }
Med label og feilmelding
Combobox støtter label og error som Input, og kobles automatisk til FormField. id, name og aria-* sendes videre til søkefeltet.
function ComboboxLabel() { const [value, setValue] = React.useState(""); return ( <div style={{ maxWidth: "20rem" }}> <Combobox label="Frukt" error={value ? undefined : "Velg en frukt"} value={value} onValueChange={setValue} > <ComboboxItem value="eple">Eple</ComboboxItem> <ComboboxItem value="banan">Banan</ComboboxItem> </Combobox> </div> ); }
Bruksanbefalinger
Bruk for store lister
Combobox egner seg når det er mange alternativer og brukeren trenger å søke. For korte lister (under 7 elementer) er vanlig Select ofte tilstrekkelig.
Ikke bruk for korte lister
Når det er få, oversiktlige alternativer er Select enklere å bruke. Combobox tilfører unødvendig kompleksitet for korte lister.
Tilgjengelighet
- Følger WAI-ARIA Combobox-mønsteret
- Full tastaturnavigasjon: piltaster, Enter, Escape
role="combobox"settes på søkefeltet, ogaria-expandedfølger faktisk åpen/lukket-tilstandlabel-propen (eller enFormFieldmed<Label>) kobler label til søkefeltet- Valgt verdi beholdes når listen åpnes og lukkes uten at brukeren skriver; den nullstilles bare hvis brukeren tømmer feltet
aria-autocomplete="list"på søkefeltet- Skjermlesere annonserer antall filtrerte resultater
- Fokus returneres til trigger ved lukking
Props
Combobox
| Prop | Type | Default | Beskrivelse |
|---|---|---|---|
value | string | — | Valgt verdi (kontrollert) |
onValueChange | (value: string) => void | — | Kalles når bruker velger et alternativ |
label | ReactNode | — | Synlig label over feltet |
error | ReactNode | — | Feilmelding under feltet |
placeholder | string | "Velg..." | Plassholdertekst i trigger og søkefelt |
disabled | boolean | false | Deaktiverer hele komponenten |
required | boolean | false | Marker som påkrevd |
className | string | — | Ekstra CSS-klasser for trigger |
emptyMessage | string | "Ingen resultater." | Tekst vist ved ingen treff |
onSearchChange | (search: string) => void | — | Kalles ved hvert tastetrykk (for asynkront søk) |
loading | boolean | false | Viser lasteindikator |
shouldFilter | boolean | true | cmdk-filtrering. Sett false for asynkront søk |
open | boolean | — | Kontrollert åpne-tilstand |
onOpenChange | (open: boolean) => void | — | Kalles når åpne-tilstand endres |
ComboboxItem
| Prop | Type | Default | Beskrivelse |
|---|---|---|---|
value | string | — | Verdien til alternativet |
disabled | boolean | false | Deaktiver dette alternativet |
ComboboxGroup
| Prop | Type | Default | Beskrivelse |
|---|---|---|---|
heading | string | — | Overskrift for gruppen |