Skip to content
bref / ui

Svelte components, simply.

Star

Combobox

Search local option labels while selected IDs stay separate from the query.

Usage

Selected: banana; changes: 0

Svelte
<script lang="ts">
	import { Combobox } from 'bref-ui';
	let fruit = $state<string | undefined>();
	const items = [{ id: 'apple', label: 'Apple' }];
</script>

<Combobox aria-label="Fruit" {items} bind:value={fruit} name="fruit" />

Playground

Live preview

Selected: none; changes: 0

Settings

Appearance
Selection
Options
View generated code
Svelte
<script lang="ts">
	import { Combobox } from 'bref-ui';
	import type { SelectOptionDataProps } from 'bref-ui/types';
	const items: SelectOptionDataProps[] = [
		{
			id: 'apple',
			label: 'Apple',
			icon: {
				name: 'favorite',
				filled: false
			}
		},
		{
			id: 'apricot',
			label: 'Apricot'
		},
		{
			id: 'banana',
			label: 'Banana'
		},
		{
			id: 'pear',
			label: 'Pear',
			disabled: true
		}
	];
	let value = $state<string | string[] | undefined>(undefined);
	let changes = $state(0);
</script>

<label for="playground-combobox">Choose fruit</label>
<Combobox
	id="playground-combobox"
	{items}
	bind:value
	size="medium"
	disabled={false}
	placeholder={'Select…'}
	emptyMessage={{ message: 'No options found', icon: { name: 'search', filled: false } }}
	wide={false}
	variant="soft"
	readonly={false}
	onChange={() => changes++}
/>
<p role="status">Selected: {JSON.stringify(value) ?? 'none'}; changes: {changes}</p>

Sizes

Size applies to the input and options. Compact option rows sit in a contextual glass panel; the input keeps its opaque field fill.

States

An explicit aria-invalid attribute gives the visible input an error edge.

Multiple: none

Pear is disabled. The shared theme control switches light and dark modes.

Forms and keyboard

No submission yet. Current value: none

Typing filters labels. Arrows move the active option, Enter selects, and Escape or blur restores the selection. A composition Enter does not select. Form reset restores initial IDs. Required validation uses the hidden native form control; it does not automatically set aria-invalid on the visible input.

Props

Component props
PropTypeRequiredDefaultDescription
itemsreadonly SelectOptionDataProps[]Yes—Unique IDs, labels, optional icons and disabled state.
valuestring | string[]NoundefinedBindable selected ID or IDs; an array enables multiple selection.
onChange(value: string | string[]) => voidNoOmittedCalled when a user changes selection.
idstringNoGeneratedInput ID for label association.
placeholderstringNoSelect…Text shown for an empty selection.
emptyMessageSelectEmptyPropsNo{ message: 'No options found' }Empty results text and optional decorative icon.
sizeBaseSizeNomediumControl and option size.
disabledbooleanNofalseDisable the control and close the popup.
variantExclude<Variant, 'filled'>NosoftNeutral or soft input appearance.
widebooleanNofalseFill the available input width.

Supported native attributes: id, title, autocomplete, autofocus, tabindex, readonly, name, form, required . Use an external label or aria-label / aria-labelledby ; aria-describedby, aria-invalid, aria-errormessage are forwarded. Supported events: oninput, onkeydown, onblur, onfocus, onclick, oncompositionstart, oncompositionend . bind:value tracks selected IDs; typed text remains private. No snippets are exposed.

Long choices and scrolling

Long labels truncate within the panel. Arrow keys and Home or End move the active row into view. Selected rows keep a primary tick; hover and keyboard activity use separate tonal fills.