6 Select
L4stIdi0t edited this page 2026-10-09 22:01:06 +02:00
This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

Select

Custom accessible select (APG "select-only combobox"): DOM focus stays on the trigger, the highlighted option is tracked via aria-activedescendant.

Full keyboard: ↑/↓ navigate, Home/End jump, type-ahead, Enter/Space select, Escape/Tab close. Click-outside closes. Inspired by melt-next's select.

Forms · two-way: bind:value · submits in a form with name · portalled to <body> · keyboard contract

<script lang="ts">
	import { Select } from '@l4st/driftwood';
</script>
Light Dark
select select in dark mode
select-open select-open in dark mode

Props

Prop Type Default What it does
options required SelectOption[] — In render order; a disabled option is skipped by the keyboard.
value bind: string — The selected option's value.
placeholder string 'Select…' Trigger text when nothing is selected.
disabled boolean false Blocks opening.
class string — Merged with the component's own classes, last — so yours win.
id string — Points a <Label for=…> at the trigger.
name string — Submits the selected value with the form.
aria-label string — Accessible name, when no visible <Label for=…> points at this.
aria-labelledby string — Id of the element that names this, instead of aria-label.
onValueChange (value: string) => void — Fires with the newly selected value.

Everything not listed above is spread onto the underlying element (HTMLButtonAttributes): aria-*, data-*, event handlers, and the rest of the native attributes.

Types

export type SelectOption = { value: string; label: string; disabled?: boolean };

Keyboard

Key Does
↑ / ↓ move the active option
Home / End first / last option
a–z type-ahead to an option
Enter / Space select the active option and close
Escape / Tab close, focus stays on the trigger

Example

The markup behind the screenshot above, lifted from src/routes/shots/ — so it compiles, and it is exactly what produced the image.

<Select options={options} bind:value={scope} aria-label="Scan scope" />

Forms · Field · Input · FileInput · FileList · Textarea · CodeEditor · Combobox · RadioGroup · NumberInput · InlineEdit · Label · MultiSelect · DatePicker · TagsInput · Checkbox · Switch · Slider


← All components · Getting started · Theming · source