Select ported
A compact choice field with a keyboard friendly menu.
A labelled choice field whose shown value rolls in the direction of the list. Built on Bits UI Select for accessible keyboard navigation and typeahead.
Loading demo…
Guidance
When to use
- A short fixed list where typing is not needed, such as region or sort order.
- Form fields that should submit natively through the hidden input name.
- Dropdown selectors requiring clean keyboard navigation and typeahead.
When not to use
- Use combobox for long or searchable lists.
- Use multi-select when several values can be chosen.
- Use segmented-control for two to four choices that should stay visible.
pnpm dlx shadcn-svelte@latest add @arcui/selectUsage
<script lang="ts">
import { Select } from '$lib/components/select';
let region = $state('eu');
const options = [
{ value: 'us', label: 'United States' },
{ value: 'eu', label: 'Europe' },
{ value: 'ap', label: 'Asia Pacific', disabled: true },
{ value: 'sa', label: 'South America' }
];
</script>
<Select
label="Region"
bind:value={region}
{options}
description="Select the primary deployment region for your cluster."
/>Variants & Examples
Controlled with Description
Two-way binding via bind:value with helper text linked through aria-describedby.
<Select
label="Region"
bind:value={selectedRegion}
options={regionOptions}
description="Linked helper text for assistive technology."
/>Disabled and Disabled Options
Supports disabling individual options or the entire select trigger.
<Select
label="Restricted Field"
value="us"
disabled
options={regionOptions}
/>API Reference
| Prop | Type | Default | Description |
|---|---|---|---|
label | string | – | Visible label for the trigger, linked via for attribute. |
options | SelectOption[] | – | Array of { value: string; label: string; disabled?: boolean } items in list order. |
value | string | undefined | Controlled selected value; supports two-way bind:value. |
defaultValue | string | '' | Initial value when uncontrolled. |
onValueChange | (value: string) => void | – | Callback fired when an option is selected. |
open | boolean | undefined | Controlled open state of the dropdown; supports two-way bind:open. |
onOpenChange | (open: boolean) => void | – | Callback fired when dropdown opens or closes. |
placeholder | string | 'Select an option' | Placeholder text displayed when no value is selected. |
description | string | – | Helper copy rendered below the trigger, linked through aria-describedby. |
disabled | boolean | false | Whether the select is disabled. |
name | string | – | Form submission input name. |
required | boolean | false | Whether selection is required for form validation. |
id | string | – | Trigger ID; auto-generated via $props.id() when omitted. |
class | string | – | Additional CSS class applied to the trigger element. |
Keyboard Interactions
| Key | Action |
|---|---|
Enter / Space / ArrowDown | Opens the list from the trigger. |
ArrowUp / ArrowDown | Moves highlight between enabled items in the list. |
Enter / Space | Selects the highlighted item and closes the dropdown. |
Escape | Closes the dropdown without changing the selected value. |
Type a letter | Jumps directly to the next item starting with that letter (typeahead). |
Accessibility
- Built on Bits UI Select: provides native role="combobox" on trigger and role="listbox" on content.
- Trigger is linked to label with for/id, and to description through aria-describedby.
- Real value renders in a visually hidden input for form submission; animated copy is aria-hidden.
- Focus is properly trapped and returned to trigger on close.
Motion
Phase 1 still-state: Selected value renders in trigger valueText container. Content animates in and out with CSS keyframes (select-in / select-out). Chevron rotates 180deg when open. Phase 2 wires directional value roll (later option rises from below, earlier drops from above with soft blur filter). Reduced motion swaps value with instant crossfade.
Notes for AI
- Pick for short fixed lists where typing is not needed.
- Two-way binding is available via bind:value={selected}.
- Use options array with value and label properties; disabled flag is optional per item.
Source of truth: registry/components/select/select.tsx