Combobox

A searchable single-select with grouped options, custom values, rich snippets, and a native datalist fallback.

registry:ui Registry JSON

Value: sveltekit

Value: None

Installation

pnpm dlx shadcn-svelte@latest add https://shadcn.cptckp.com/r/combobox.json

The CLI copies the source into your project and installs every dependency listed below.

Import { Combobox } and provide a unique id, form name, and options with label/value pairs. Bind value and optionally open; use group, keywords, and disabled on options. Customize item(option, selected) and selected(option) snippets, or enable allowCustom and clearLabel. The trigger defaults to secondary. Without JavaScript this renders an input and datalist; always validate required values, option membership, and custom text on the server.

Usage

import { Combobox, type ComboboxOption } from '$lib/components/ui/combobox/index.js';
example.svelte
svelte
<script lang="ts">
	import CheckIcon from '@lucide/svelte/icons/check';
	import { Combobox, type ComboboxOption } from '$lib/components/ui/combobox/index.js';

	const options = [
		{ group: 'Frameworks', label: 'SvelteKit', value: 'sveltekit', description: 'Full-stack Svelte', keywords: 'SvelteKit sveltekit full-stack' },
		{ group: 'Frameworks', label: 'Astro', value: 'astro', description: 'Content-driven sites' },
		{ group: 'Libraries', label: 'Svelte', value: 'svelte', description: 'Reactive interfaces' },
		{ group: 'Libraries', label: 'React', value: 'react', description: 'Component-based interfaces' }
	] satisfies (ComboboxOption & { description: string })[];

	let framework = $state('sveltekit');
	let technology = $state('');
</script>

<div class="grid w-full gap-6 sm:grid-cols-2">
	<section class="flex min-w-0 flex-col gap-3">
		<label for="framework" class="text-sm font-medium">Grouped selection</label>
		<Combobox
			id="framework"
			name="framework"
			{options}
			bind:value={framework}
			placeholder="Select a framework"
			searchPlaceholder="Search frameworks..."
			clearLabel="Clear selection"
		/>
		<p class="text-sm text-muted-foreground">Value: {framework || 'None'}</p>
	</section>

	<section class="flex min-w-0 flex-col gap-3">
		<label for="technology" class="text-sm font-medium">Rich options and custom values</label>
		<Combobox
			id="technology"
			name="technology"
			{options}
			bind:value={technology}
			allowCustom
			placeholder="Select or add a technology"
			searchPlaceholder="Search or type a new value..."
		>
			{#snippet item(option, isSelected)}
				<div class="flex min-w-0 flex-1 flex-col">
					<span class="truncate">{option.label}</span>
					<span class="truncate text-xs text-muted-foreground">{option.description}</span>
				</div>
				{#if isSelected}<CheckIcon />{/if}
			{/snippet}
			{#snippet selected(option)}
				{option.label} ยท {option.group}
			{/snippet}
		</Combobox>
		<p class="text-sm text-muted-foreground">Value: {technology || 'None'}</p>
	</section>
</div>

Files & dependencies

Installed asSource
combobox/combobox.sveltesrc/lib/registry/ui/combobox/combobox.svelte
combobox/combobox.tssrc/lib/registry/ui/combobox/combobox.ts
combobox/index.tssrc/lib/registry/ui/combobox/index.ts

npm dependencies

  • @lucide/svelte@^1.28.0

Registry dependencies

  • button
  • command
  • input
  • popover