Combobox
A single-choice text field over a closed set of options — typing filters a portalled listbox, and a value outside the list can never be selected.
Preview
<script lang="ts">
import { Combobox } from "fancy-ui-svelte";
const frameworks = [
{ value: "svelte-5", label: "Svelte 5" },
{ value: "sveltekit", label: "SvelteKit" },
{ value: "react", label: "React" },
{ value: "vue", label: "Vue" },
];
let framework = $state("");
</script>
<Combobox options={frameworks} bind:value={framework} label="Framework" placeholder="Search…" />Installation
Usage
<script lang="ts">
import { Combobox } from 'fancy-ui-svelte';
</script>
<Combobox />Examples
Basic Usage
Four frameworks, filtered by typing.
<script lang="ts">
import { Combobox } from "$lib/fancy-ui/combobox";
const frameworks = [
{ value: "svelte-5", label: "Svelte 5" },
{ value: "sveltekit", label: "SvelteKit" },
{ value: "react", label: "React" },
{ value: "vue", label: "Vue" },
];
let framework = $state("");
</script>
<Combobox options={frameworks} bind:value={framework} label="Framework" placeholder="Search…" />Custom Filter
Matches by value prefix instead of the label — shows the highlight degrading gracefully when the match isn't a literal label substring.
<script lang="ts">
// The default filter matches substrings of the label. This one matches
// only a prefix of the *value* instead, so typing the short slug ("sk")
// finds "SvelteKit" even though "sk" never appears in its label.
import { Combobox, type ComboboxOption } from "$lib/fancy-ui/combobox";
const frameworks: ComboboxOption[] = [
{ value: "svelte-5", label: "Svelte 5" },
{ value: "sk", label: "SvelteKit" },
{ value: "react", label: "React" },
{ value: "vue", label: "Vue" },
];
let framework = $state("");
function filterByValuePrefix(option: ComboboxOption, query: string): boolean {
return option.value.toLowerCase().startsWith(query.toLowerCase());
}
</script>
<Combobox
options={frameworks}
bind:value={framework}
filter={filterByValuePrefix}
label="Framework (matched by slug)"
placeholder="Try “sk”…"
/>With FormField
Wrapped in FormField — required and the error message driven by context.
<script lang="ts">
// FormField supplies controlId, aria-describedby and aria-invalid to
// Combobox through context — no id or invalid prop needed here.
import { FormField } from "$lib/fancy-ui/form-field";
import { Combobox } from "$lib/fancy-ui/combobox";
const frameworks = [
{ value: "svelte-5", label: "Svelte 5" },
{ value: "sveltekit", label: "SvelteKit" },
{ value: "react", label: "React" },
{ value: "vue", label: "Vue" },
];
let framework = $state("");
</script>
<FormField
label="Framework"
required
error={framework ? undefined : "Pick a framework before continuing."}
class="w-full max-w-sm"
>
<Combobox options={frameworks} bind:value={framework} />
</FormField>Props
| Prop | Type | Default | Description |
|---|---|---|---|
options * | ComboboxOption[] | - | The closed set of selectable options. |
value | string | "" | The selected option's value, bindable — "" means nothing is selected. |
onValueChange | (value: string) => void | - | Called whenever the selection commits. |
placeholder | string | - | Shown while the field is empty and nothing is selected. |
disabled | boolean | false | Blocks focus and typing; excluded from form submission. |
required | boolean | false | Native required, on the visible field. |
invalid | boolean | false | Drives the error border and aria-invalid. |
id | string | - | Element id. |
name | string | - | Native name — submitted via a hidden input carrying value, not the visible label. |
label | string | - | Accessible name — for a control with no visible Label next to it. |
filter | (option: ComboboxOption, query: string) => boolean | - | Matches an option against the current query. Default: case-insensitive substring on label. |
emptyMessage | string | "No results" | Shown in the panel when no option matches the current query. |
class | string | - | Additional CSS classes. |
ref | HTMLInputElement | null | null | Bindable reference to the input element. |
Links
Related components
Autocomplete
A free-text field with a portalled panel of matching suggestions — any typed value is valid; the panel only ever helps finish it faster.
Checkbox
A tri-look checkbox — unchecked, checked, indeterminate and disabled — built on a native checkbox input
DatePicker
A field that opens a floating month grid, with full keyboard navigation (arrow keys across days, Page Up/Down across months, Shift for years), min/max and per-day disabling, and a fully localized accessible name on every day cell.