Kumo Svelte
  • Home
  • Installation
  • Colors
  • Accessibility
  • Changelog
  • Autocomplete
  • Badge
  • Banner
  • Breadcrumbs
  • Button
  • Checkbox
  • Clipboard Text
  • Cloudflare Logo
  • CodeHighlighted
  • Collapsible
  • Combobox
  • Command Palette
  • Date Picker
  • Dialog
  • Dropdown
  • Empty
  • Flow
  • Grid
  • Input
  • InputArea
  • InputGroup
  • Label
  • Layer Card
  • Link
  • Loader
  • MenuBar
  • Meter
  • Pagination
  • Popover
  • Radio
  • Select
  • Sensitive Input
  • Sidebar
  • Skeleton Line
  • Switch
  • Table
  • Table of Contents
  • Tabs
  • Text
  • Toast
  • Toolbar
  • Tooltip
  • Charts
  • Colors
  • Timeseries
  • Maps
  • Sankey
  • Custom Chart
  • Page Header
  • Resource List
  • Delete Resource
Autocomplete
kumo-svelte

Autocomplete

A free-form text input with an optional filtered suggestion list. Unlike Combobox, the value is not constrained to the items list.

<script lang="ts">
  import * as Autocomplete from "kumo-svelte/components/autocomplete";

  const fruits = ["Apple", "Apricot", "Banana", "Blueberry", "Cherry", "Mango"];
</script>

<Autocomplete.Root>
  <Autocomplete.InputGroup placeholder="Search fruits…" />
  <Autocomplete.Content>
    <Autocomplete.List>
      {#each fruits as fruit (fruit)}
        <Autocomplete.Item value={fruit}>{fruit}</Autocomplete.Item>
      {/each}
      <Autocomplete.Empty>No fruits found.</Autocomplete.Empty>
    </Autocomplete.List>
  </Autocomplete.Content>
</Autocomplete.Root>

Import

import * as Autocomplete from "kumo-svelte/components/autocomplete";

When to use

Use Autocomplete when the input value can be free-form text and suggestions are optional hints. Use Combobox instead when the selected value must come from the predefined list.

Usage

<script lang="ts">
  import * as Autocomplete from "kumo-svelte/components/autocomplete";
  const fruits = ["Apple", "Banana", "Cherry"];
</script>

<Autocomplete.Root>
  <Autocomplete.InputGroup placeholder="Search fruits…" />
  <Autocomplete.Content>
    <Autocomplete.List>
      {#each fruits as fruit (fruit)}
        <Autocomplete.Item value={fruit}>{fruit}</Autocomplete.Item>
      {/each}
      <Autocomplete.Empty>No fruits found.</Autocomplete.Empty>
    </Autocomplete.List>
  </Autocomplete.Content>
</Autocomplete.Root>

Controlled

Bind value or pass onValueChange for controlled usage.

<script lang="ts">
  import * as Autocomplete from "kumo-svelte/components/autocomplete";

  const fruits = ["Apple", "Apricot", "Banana", "Blueberry", "Cherry", "Mango"];

  let value = $state("");
</script>

<div class="flex flex-col gap-3 w-80">
  <Autocomplete.Root bind:value>
    <Autocomplete.InputGroup placeholder="Type a fruit…" />
    <Autocomplete.Content>
      <Autocomplete.List>
        {#each fruits as fruit (fruit)}
          <Autocomplete.Item value={fruit}>{fruit}</Autocomplete.Item>
        {/each}
        <Autocomplete.Empty>No fruits found.</Autocomplete.Empty>
      </Autocomplete.List>
    </Autocomplete.Content>
  </Autocomplete.Root>
  {#if value}
    <p class="text-sm text-kumo-subtle">Value: <span class="font-medium text-kumo-default">{value}</span></p>
  {/if}
</div>

With Field

Add label, description, and required to enable the built-in Field wrapper.

Start typing to filter countries

<script lang="ts">
  import * as Autocomplete from "kumo-svelte/components/autocomplete";

  const countries = [
    { code: "us", label: "United States", value: "United States" },
    { code: "gb", label: "United Kingdom", value: "United Kingdom" },
    { code: "de", label: "Germany", value: "Germany" },
    { code: "fr", label: "France", value: "France" },
    { code: "jp", label: "Japan", value: "Japan" },
  ];

  interface Props {
    error?: string;
  }

  let { error }: Props = $props();
</script>

<div class="w-80">
  <Autocomplete.Root
    label="Country"
    description={error ? undefined : "Start typing to filter countries"}
    {error}
    required
  >
    <Autocomplete.InputGroup placeholder="Search countries…" />
    <Autocomplete.Content>
      <Autocomplete.List>
        {#each countries as country (country.code)}
          <Autocomplete.Item value={country.value} label={country.label}>
            {country.label}
          </Autocomplete.Item>
        {/each}
        <Autocomplete.Empty>No countries found.</Autocomplete.Empty>
      </Autocomplete.List>
    </Autocomplete.Content>
  </Autocomplete.Root>
</div>

Error State

Display validation errors with the error prop.

Please enter a valid country

<script lang="ts">
  import * as Autocomplete from "kumo-svelte/components/autocomplete";

  const countries = [
    { code: "us", label: "United States", value: "United States" },
    { code: "gb", label: "United Kingdom", value: "United Kingdom" },
    { code: "de", label: "Germany", value: "Germany" },
    { code: "fr", label: "France", value: "France" },
    { code: "jp", label: "Japan", value: "Japan" },
  ];
</script>

<div class="w-80">
  <Autocomplete.Root label="Country" error="Please enter a valid country">
    <Autocomplete.InputGroup placeholder="Search countries…" />
    <Autocomplete.Content>
      <Autocomplete.List>
        {#each countries as country (country.code)}
          <Autocomplete.Item value={country.value} label={country.label}>
            {country.label}
          </Autocomplete.Item>
        {/each}
        <Autocomplete.Empty>No countries found.</Autocomplete.Empty>
      </Autocomplete.List>
    </Autocomplete.Content>
  </Autocomplete.Root>
</div>

Grouped

Group items into categories using Autocomplete.Group and Autocomplete.GroupLabel.

<script lang="ts">
  import * as Autocomplete from "kumo-svelte/components/autocomplete";

  const servers = [
    {
      value: "North America",
      items: [
        { label: "US East", value: "us-east" },
        { label: "US West", value: "us-west" },
        { label: "Canada", value: "canada" },
      ],
    },
    {
      value: "Europe",
      items: [
        { label: "Germany", value: "germany" },
        { label: "France", value: "france" },
        { label: "United Kingdom", value: "uk" },
      ],
    },
  ];
</script>

<Autocomplete.Root>
  <Autocomplete.InputGroup placeholder="Select region…" />
  <Autocomplete.Content>
    <Autocomplete.List>
      {#each servers as region (region.value)}
        <Autocomplete.Group>
          <Autocomplete.GroupLabel>{region.value}</Autocomplete.GroupLabel>
          {#each region.items as item (item.value)}
            <Autocomplete.Item value={item.label} label={item.label}>{item.label}</Autocomplete.Item>
          {/each}
        </Autocomplete.Group>
      {/each}
      <Autocomplete.Empty>No regions found.</Autocomplete.Empty>
    </Autocomplete.List>
  </Autocomplete.Content>
</Autocomplete.Root>

Sizes

The size prop on Autocomplete.InputGroup supports xs, sm, base, and lg.

<script lang="ts">
  import * as Autocomplete from "kumo-svelte/components/autocomplete";

  const fruits = ["Apple", "Apricot", "Banana", "Blueberry", "Cherry", "Mango"];
</script>

<div class="flex flex-wrap items-center gap-4">
  <Autocomplete.Root>
    <Autocomplete.InputGroup size="xs" placeholder="xs" />
    <Autocomplete.Content>
      <Autocomplete.List>
        {#each fruits as fruit (fruit)}
          <Autocomplete.Item value={fruit}>{fruit}</Autocomplete.Item>
        {/each}
        <Autocomplete.Empty>No fruits found.</Autocomplete.Empty>
      </Autocomplete.List>
    </Autocomplete.Content>
  </Autocomplete.Root>
  <Autocomplete.Root>
    <Autocomplete.InputGroup size="sm" placeholder="sm" />
    <Autocomplete.Content>
      <Autocomplete.List>
        {#each fruits as fruit (fruit)}
          <Autocomplete.Item value={fruit}>{fruit}</Autocomplete.Item>
        {/each}
        <Autocomplete.Empty>No fruits found.</Autocomplete.Empty>
      </Autocomplete.List>
    </Autocomplete.Content>
  </Autocomplete.Root>
  <Autocomplete.Root>
    <Autocomplete.InputGroup size="base" placeholder="base (default)" />
    <Autocomplete.Content>
      <Autocomplete.List>
        {#each fruits as fruit (fruit)}
          <Autocomplete.Item value={fruit}>{fruit}</Autocomplete.Item>
        {/each}
        <Autocomplete.Empty>No fruits found.</Autocomplete.Empty>
      </Autocomplete.List>
    </Autocomplete.Content>
  </Autocomplete.Root>
  <Autocomplete.Root>
    <Autocomplete.InputGroup size="lg" placeholder="lg" />
    <Autocomplete.Content>
      <Autocomplete.List>
        {#each fruits as fruit (fruit)}
          <Autocomplete.Item value={fruit}>{fruit}</Autocomplete.Item>
        {/each}
        <Autocomplete.Empty>No fruits found.</Autocomplete.Empty>
      </Autocomplete.List>
    </Autocomplete.Content>
  </Autocomplete.Root>
</div>

Custom Filtering

For advanced matching or async search, keep filtered items in application state and render that list.

<Autocomplete.Root>
  <Autocomplete.InputGroup placeholder="Search countries…" />
  <Autocomplete.Content>
    <Autocomplete.List>
      {#each filteredCountries as country (country.value)}
        <Autocomplete.Item value={country.value} label={country.label}>
          {country.label}
        </Autocomplete.Item>
      {/each}
      <Autocomplete.Empty>No countries found.</Autocomplete.Empty>
    </Autocomplete.List>
  </Autocomplete.Content>
</Autocomplete.Root>

API Reference

Autocomplete

PropTypeDefault
allowDeselectbooleantrue
childrenSnippet—
defaultValuestring""
descriptionSnippet | string—
disabledbooleanfalse
errorstring | { message: Snippet | string; match: FieldErrorMatch }—
labelSnippet | string—
labelTooltipSnippet—
namestring—
onOpenChange(open: boolean) => void—
onValueChange(value: string) => void—
openbooleanfalse
requiredboolean—
sizeKumoAutocompleteSizeKUMO_AUTOCOMPLETE_DEFAULT_VARIANTS.size
valuestringdefaultValue

Autocomplete.Content

PropTypeDefault
childrenSnippet—
classstring—
containerPortalProps["to"]—
sideOffsetnumber4

Autocomplete.Empty

PropTypeDefault
childrenSnippet—
classstring—

Autocomplete.Group

PropTypeDefault
childrenSnippet—

Autocomplete.GroupLabel

PropTypeDefault
childrenSnippet—
classstring—

Autocomplete.Input

PropTypeDefault
aria-labelstring—
autocompleteHTMLInputAttributes["autocomplete"]—
classstring—
clearOnDeselectboolean—
defaultValuestring—
disabledboolean—
idstring—
namestring—
onblur(event: FocusEvent & { currentTarget: HTMLInputElement }) => void—
onfocus(event: FocusEvent & { currentTarget: HTMLInputElement }) => void—
oninput(event: Event & { currentTarget: HTMLInputElement }) => void—
onkeydown(event: KeyboardEvent & { currentTarget: HTMLInputElement }) => void—
onValueChange(value: string) => void—
placeholderstring—
requiredboolean—
sizeKumoAutocompleteSize—

Autocomplete.Item

PropTypeDefault
childrenSnippet—
disabledbooleanfalse
labelstring—
value*string—

Autocomplete.List

PropTypeDefault
childrenSnippet—
classstring—

Autocomplete.Separator

PropTypeDefault
classstring—

On this page

  • Import
  • When to use
  • Usage
  • Controlled
  • With Field
  • Error State
  • Grouped
  • Sizes
  • Custom Filtering
  • API Reference
    • Autocomplete
    • Autocomplete.Content
    • Autocomplete.Empty
    • Autocomplete.Group
    • Autocomplete.GroupLabel
    • Autocomplete.Input
    • Autocomplete.Item
    • Autocomplete.List
    • Autocomplete.Separator