Autocomplete
kumo-svelte
<script lang="ts">
  import { Autocomplete } from 'kumo-svelte';

  const fruits = [
  'Apple',
  'Apricot',
  'Avocado',
  'Banana',
  'Blackberry',
  'Blueberry',
  'Cantaloupe',
  'Cherry',
  'Coconut',
  'Cranberry',
  'Date',
  'Dragon Fruit',
  'Fig',
  'Grape',
  'Grapefruit',
  'Guava',
  'Honeydew',
  'Kiwi',
  'Lemon',
  'Lime',
  'Lychee',
  'Mango',
  'Nectarine',
  'Orange',
  'Papaya',
  'Passion Fruit',
  'Peach',
  'Pear',
  'Pineapple',
  'Plum',
  'Raspberry',
  'Strawberry',
  'Watermelon'
];
</script>

<Autocomplete items={fruits}>
  <Autocomplete.InputGroup placeholder="Search fruits…" />
  <Autocomplete.Content>
    <Autocomplete.List>
      {#snippet children(item)}
        <Autocomplete.Item value={item}>{item}</Autocomplete.Item>
      {/snippet}
    </Autocomplete.List>
  </Autocomplete.Content>
</Autocomplete>

Installation

Barrel

import { Autocomplete } from 'kumo-svelte';

Granular

import { 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.

Controlled

Pass value and onValueChange for controlled usage.

<script lang="ts">
  import { Autocomplete } from 'kumo-svelte';

  const fruits = [
  'Apple',
  'Apricot',
  'Avocado',
  'Banana',
  'Blackberry',
  'Blueberry',
  'Cantaloupe',
  'Cherry',
  'Coconut',
  'Cranberry',
  'Date',
  'Dragon Fruit',
  'Fig',
  'Grape',
  'Grapefruit',
  'Guava',
  'Honeydew',
  'Kiwi',
  'Lemon',
  'Lime',
  'Lychee',
  'Mango',
  'Nectarine',
  'Orange',
  'Papaya',
  'Passion Fruit',
  'Peach',
  'Pear',
  'Pineapple',
  'Plum',
  'Raspberry',
  'Strawberry',
  'Watermelon'
];

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

<div class="flex w-80 flex-col gap-3">
  <Autocomplete bind:value items={fruits}>
    <Autocomplete.InputGroup placeholder="Type a fruit…" />
    <Autocomplete.Content>
      <Autocomplete.List>
        {#snippet children(item)}
          <Autocomplete.Item value={item}>{item}</Autocomplete.Item>
        {/snippet}
      </Autocomplete.List>
    </Autocomplete.Content>
  </Autocomplete>
  {#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 { Autocomplete } from 'kumo-svelte';

  const countries = [
  { label: 'United States', value: 'us' },
  { label: 'United Kingdom', value: 'gb' },
  { label: 'Germany', value: 'de' },
  { label: 'France', value: 'fr' },
  { label: 'Japan', value: 'jp' },
  { label: 'China', value: 'cn' },
  { label: 'India', value: 'in' },
  { label: 'Brazil', value: 'br' },
  { label: 'Canada', value: 'ca' },
  { label: 'Australia', value: 'au' }
];
</script>

<div class="w-80">
  <Autocomplete
    items={countries}
    label="Country"
    description="Start typing to filter countries"
  >
    <Autocomplete.InputGroup placeholder="Search countries…" />
    <Autocomplete.Content>
      <Autocomplete.List>
        {#snippet children(item)}
          <Autocomplete.Item value={item}>{item.label}</Autocomplete.Item>
        {/snippet}
      </Autocomplete.List>
    </Autocomplete.Content>
  </Autocomplete>
</div>

Error State

Display validation errors with the error prop.

Please enter a valid country
<script lang="ts">
  import { Autocomplete } from 'kumo-svelte';

  const countries = [
  { label: 'United States', value: 'us' },
  { label: 'United Kingdom', value: 'gb' },
  { label: 'Germany', value: 'de' },
  { label: 'France', value: 'fr' },
  { label: 'Japan', value: 'jp' },
  { label: 'China', value: 'cn' },
  { label: 'India', value: 'in' },
  { label: 'Brazil', value: 'br' },
  { label: 'Canada', value: 'ca' },
  { label: 'Australia', value: 'au' }
];
</script>

<div class="w-80">
  <Autocomplete
    items={countries}
    label="Country"
    error={{ message: 'Please enter a valid country', match: true }}
  >
    <Autocomplete.InputGroup placeholder="Search countries…" />
    <Autocomplete.Content>
      <Autocomplete.List>
        {#snippet children(item)}
          <Autocomplete.Item value={item}>{item.label}</Autocomplete.Item>
        {/snippet}
      </Autocomplete.List>
    </Autocomplete.Content>
  </Autocomplete>
</div>

Grouped

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

<script lang="ts">
  import { Autocomplete } from 'kumo-svelte';

  const servers = [
    {
      label: 'North America',
      value: 'North America',
      items: [
        { label: 'US East (Virginia)', value: 'us-east-1' },
        { label: 'US West (Oregon)', value: 'us-west-2' },
        { label: 'Canada (Central)', value: 'ca-central-1' }
      ]
    },
    {
      label: 'Europe',
      value: 'Europe',
      items: [
        { label: 'EU West (Ireland)', value: 'eu-west-1' },
        { label: 'EU Central (Frankfurt)', value: 'eu-central-1' },
        { label: 'EU North (Stockholm)', value: 'eu-north-1' }
      ]
    },
    {
      label: 'Asia Pacific',
      value: 'Asia Pacific',
      items: [
        { label: 'AP Southeast (Singapore)', value: 'ap-southeast-1' },
        { label: 'AP Northeast (Tokyo)', value: 'ap-northeast-1' },
        { label: 'AP South (Mumbai)', value: 'ap-south-1' }
      ]
    }
  ];
</script>

<Autocomplete items={servers}>
  <Autocomplete.InputGroup placeholder="Select region…" />
  <Autocomplete.Content>
    <Autocomplete.List>
      {#snippet children(group)}
        <Autocomplete.Group items={group.items}>
          <Autocomplete.GroupLabel>{group.label}</Autocomplete.GroupLabel>
          <Autocomplete.Collection>
            {#snippet children(item)}
              <Autocomplete.Item value={item}>{item.label}</Autocomplete.Item>
            {/snippet}
          </Autocomplete.Collection>
        </Autocomplete.Group>
      {/snippet}
    </Autocomplete.List>
  </Autocomplete.Content>
</Autocomplete>

Sizes

The size prop on Autocomplete.InputGroup supports four variants matching the Input component: xs, sm, base (default), and lg.

<script lang="ts">
  import { Autocomplete } from 'kumo-svelte';

  const fruits = [
  'Apple',
  'Apricot',
  'Avocado',
  'Banana',
  'Blackberry',
  'Blueberry',
  'Cantaloupe',
  'Cherry',
  'Coconut',
  'Cranberry',
  'Date',
  'Dragon Fruit',
  'Fig',
  'Grape',
  'Grapefruit',
  'Guava',
  'Honeydew',
  'Kiwi',
  'Lemon',
  'Lime',
  'Lychee',
  'Mango',
  'Nectarine',
  'Orange',
  'Papaya',
  'Passion Fruit',
  'Peach',
  'Pear',
  'Pineapple',
  'Plum',
  'Raspberry',
  'Strawberry',
  'Watermelon'
];
</script>

<div class="flex flex-wrap items-center gap-4">
  <Autocomplete items={fruits.slice(0, 10)}>
    <Autocomplete.InputGroup size="xs" placeholder="xs" />
    <Autocomplete.Content>
      <Autocomplete.List>
        {#snippet children(item)}
          <Autocomplete.Item value={item}>{item}</Autocomplete.Item>
        {/snippet}
      </Autocomplete.List>
    </Autocomplete.Content>
  </Autocomplete>
  <Autocomplete items={fruits.slice(0, 10)}>
    <Autocomplete.InputGroup size="sm" placeholder="sm" />
    <Autocomplete.Content>
      <Autocomplete.List>
        {#snippet children(item)}
          <Autocomplete.Item value={item}>{item}</Autocomplete.Item>
        {/snippet}
      </Autocomplete.List>
    </Autocomplete.Content>
  </Autocomplete>
  <Autocomplete items={fruits.slice(0, 10)}>
    <Autocomplete.InputGroup size="base" placeholder="base (default)" />
    <Autocomplete.Content>
      <Autocomplete.List>
        {#snippet children(item)}
          <Autocomplete.Item value={item}>{item}</Autocomplete.Item>
        {/snippet}
      </Autocomplete.List>
    </Autocomplete.Content>
  </Autocomplete>
  <Autocomplete items={fruits.slice(0, 10)}>
    <Autocomplete.InputGroup size="lg" placeholder="lg" />
    <Autocomplete.Content>
      <Autocomplete.List>
        {#snippet children(item)}
          <Autocomplete.Item value={item}>{item}</Autocomplete.Item>
        {/snippet}
      </Autocomplete.List>
    </Autocomplete.Content>
  </Autocomplete>
</div>

Filtering

Filtering is case- and accent-insensitive by default, powered by Intl.Collator under the hood. For string items, no custom filter is needed.

When filtering on a property of object items, use Autocomplete.useFilter() to preserve the built-in accent-insensitive matching:

<script lang="ts">  import { Autocomplete } from "kumo-svelte";  const { contains } = Autocomplete.useFilter();  const languages = [    { value: "pt", label: "Portuguese", emoji: "🇵🇹" },    { value: "es", label: "Spanish", emoji: "🇪🇸" }  ];  const filter = (item, query) => contains(item.label, query);</script><Autocomplete items={languages} {filter}>  <!-- ... --></Autocomplete>

To disable filtering entirely (for example, when results come from a server), pass filter={null}:

<Autocomplete items={results} filter={null}>  <!-- ... --></Autocomplete>

API Reference

Autocomplete

Root component. Wraps all sub-components and manages state.

PropTypeDefaultDescription
items *unknown[]-Array of items to display in the dropdown.
value string | number | string[]-Controlled input value.
open booleanfalseControlled open state.
children Snippet-Child snippet rendered by the component.
class string-Additional classes merged onto the root element.
label string | Snippet-Visible label content.
required boolean-Marks the field as required.
labelTooltip string | Snippet-Optional help content for the label.
description string | Snippet-Supporting description text.
error FieldError-Validation error message or matcher.
defaultValue string | number | string[]-Uncontrolled default input value.
onValueChange (value: string | number | string[]) => void-Called when the value changes.
onOpenChange (open: boolean) => void-Called when open state changes.

Autocomplete.InputGroup

Autocomplete text input with Input component styling.

PropTypeDefaultDescription
size 'xs' | 'sm' | 'base' | 'lg'"base"Size of the autocomplete input. Matches Input component sizes.
placeholder string-Placeholder text.

Autocomplete.Content

Dropdown popup container.

PropTypeDefaultDescription
align 'start' | 'center' | 'end'"start"Alignment of the popup relative to the input.
alignOffset number | string-Offset along the alignment axis.
side 'top' | 'right' | 'bottom' | 'left'"bottom"Side of the input where the popup is placed.
sideOffset number | string4Offset between the popup and the input.

Autocomplete.List

Scrollable list container with render prop.

PropTypeDefaultDescription
No component-specific props. Accepts standard HTML attributes.

Autocomplete.Item

Individual suggestion item in the list.

PropTypeDefaultDescription
value *unknown-Value associated with this item.
disabled boolean-Disables the component.

Autocomplete.Group

Groups items under a heading.

PropTypeDefaultDescription
items AutocompleteItem[][]Items rendered by the component.

Autocomplete.GroupLabel

Heading label for a group.

PropTypeDefaultDescription
No component-specific props. Accepts standard HTML attributes.

Autocomplete.Collection

Item container within a group.

PropTypeDefaultDescription
No component-specific props. Accepts standard HTML attributes.

Autocomplete.Separator

Horizontal divider between items.

PropTypeDefaultDescription
No component-specific props. Accepts standard HTML attributes.