Skip to content
Skip design navigation
Etesie Alpha
Loading account
Components · Combobox · Use

Combobox

Option data, grouping, and selection cardinality belong to the application; this recipe has one visual construction.

State

Markup

<script lang="ts">
	import { Combobox, createListCollection } from '@ark-ui/svelte';
	import { useFilter } from '@ark-ui/svelte/locale';
	import CheckIcon from '@lucide/svelte/icons/check';
	import ChevronDownIcon from '@lucide/svelte/icons/chevron-down';

	const frameworks = createListCollection({
		items: [
			{ label: 'Svelte', value: 'svelte' },
			{ label: 'React', value: 'react' },
			{ label: 'Vue', value: 'vue' }
		]
	});

	const filter = useFilter({ sensitivity: 'base' });

	let query = $state('');

	// Filtering through the collection's own `filter` keeps Ark's keyboard
	// navigation in step with what is rendered.
	const filtered = $derived(
		query.trim() ? frameworks.filter((item) => filter().contains(item, query)) : frameworks
	);
</script>

<Combobox.Root
	collection={filtered}
	inputValue={query}
	onInputValueChange={(details) => (query = details.inputValue)}
	class="combobox-root"
>
	<Combobox.Label class="combobox-label">Framework</Combobox.Label>
	<Combobox.Control class="combobox-control">
		<Combobox.Input class="combobox-input" placeholder="Choose or type…" />
		<Combobox.Trigger class="combobox-trigger" aria-label="Open options">
			<ChevronDownIcon />
		</Combobox.Trigger>
	</Combobox.Control>
	<Combobox.Positioner class="combobox-positioner">
		<Combobox.Content class="combobox-content">
			<Combobox.Empty class="combobox-empty">No matches.</Combobox.Empty>
			<Combobox.List class="combobox-list">
				{#each filtered.items as option (option.value)}
					<Combobox.Item item={option} class="combobox-item">
						<Combobox.ItemText class="combobox-item-text">{option.label}</Combobox.ItemText>
						<Combobox.ItemIndicator class="combobox-item-indicator">
							<CheckIcon />
						</Combobox.ItemIndicator>
					</Combobox.Item>
				{/each}
			</Combobox.List>
		</Combobox.Content>
	</Combobox.Positioner>
</Combobox.Root>