CwDropdown

A custom select using the ARIA combobox pattern. Focus stays on the trigger while arrow keys, Home, End and typeahead move through options; disabled options are skipped.

Basics

Readings are filtered to this site

Last event: none yet

Validation

Choose a site to continue

The required marker is visual; the control also sets aria-required.

Sizes

CwDropdown example Copy code
<CwDropdown
	{options}
	label="Site"
	hint="Readings are filtered to this site"
	required
	error={site ? undefined : 'Choose a site to continue'}
	bind:value={site}
/>
API

Usage and API reference

CwDropdown is a custom select/combobox wrapper. Pass the option list, bind the selected value, and let the component handle keyboard navigation and popover positioning.

How to think about it

  1. Build the option list first Each option needs a `label` and `value`. Add `disabled` to any item that should be visible but not selectable.
  2. Bind the selected value Use `bind:value` if the parent owns the selection state. Use `onchange` when you only need a callback.
  3. Treat errors as field-level validation Use the `error` prop when the user must make a selection before continuing.

Props and callbacks

APITypeDetails
options Required
Array<{ label: string; value: string; disabled?: boolean }>Items shown in the dropdown list.
value

Default: ''

stringSelected option value. Bind this when the parent owns state.
label
stringVisible field label.
placeholder

Default: Select...

stringText shown before a value is selected.
required

Default: false

booleanMarks the hidden native input as required for form validation.
disabled

Default: false

booleanPrevents opening the list or changing the value.
error
stringValidation message rendered below the field.
onchange
(value: string) => voidCalled when the selected value changes.
name / autocomplete
stringOptional native form attributes forwarded to the hidden input.
size

Default: 'md'

'sm' | 'md' | 'lg'Control height and font scale, shared with CwButton and every other form control.
hint
stringHelper text under the field. Replaced by `error` when both are set.
labels
{ empty? }Text shown when `options` is empty.

Copy-paste examples

Each snippet is a complete, working example you can paste into a Svelte 5 component.

Controlled dropdown

This is the most common usage in forms and filters.

Controlled dropdown Copy code
<script lang="ts">
	const fruitOptions = [
		{ label: 'Apple', value: 'apple' },
		{ label: 'Banana', value: 'banana' },
		{ label: 'Dragonfruit', value: 'dragonfruit', disabled: true }
	];
	let selectedFruit = $state('');
</script>

<CwDropdown
	options={fruitOptions}
	label="Fruit"
	placeholder="Choose a fruit..."
	bind:value={selectedFruit}
/>
Form validation and change callback

Use `required` and `error` when the selection is mandatory.

Form validation and change callback Copy code
<script lang="ts">
	const siteOptions = [
		{ label: 'North greenhouse', value: 'north' },
		{ label: 'South greenhouse', value: 'south' }
	];
	let site = $state('');
	let error = $state('');

	function handleChange(value: string) {
		site = value;
		error = '';
	}
</script>

<CwDropdown
	options={siteOptions}
	name="site"
	required
	label="Deployment site"
	error={error}
	value={site}
	onchange={handleChange}
/>