Hopp til hovedinnhold
Stabil

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, og aria-expanded følger faktisk åpen/lukket-tilstand
  • label-propen (eller en FormField med <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

PropTypeDefaultBeskrivelse
valuestring—Valgt verdi (kontrollert)
onValueChange(value: string) => void—Kalles når bruker velger et alternativ
labelReactNode—Synlig label over feltet
errorReactNode—Feilmelding under feltet
placeholderstring"Velg..."Plassholdertekst i trigger og søkefelt
disabledbooleanfalseDeaktiverer hele komponenten
requiredbooleanfalseMarker som påkrevd
classNamestring—Ekstra CSS-klasser for trigger
emptyMessagestring"Ingen resultater."Tekst vist ved ingen treff
onSearchChange(search: string) => void—Kalles ved hvert tastetrykk (for asynkront søk)
loadingbooleanfalseViser lasteindikator
shouldFilterbooleantruecmdk-filtrering. Sett false for asynkront søk
openboolean—Kontrollert åpne-tilstand
onOpenChange(open: boolean) => void—Kalles når åpne-tilstand endres

ComboboxItem

PropTypeDefaultBeskrivelse
valuestring—Verdien til alternativet
disabledbooleanfalseDeaktiver dette alternativet

ComboboxGroup

PropTypeDefaultBeskrivelse
headingstring—Overskrift for gruppen