Dropdown for selecting from a list of options with grouping support
Tags: component form selection
Select allows users to choose from a predefined list of options in a dropdown menu.
Import
<script>
import { Select } from '@classic-homes/theme-svelte';
</script>Basic Usage
<script>
let value = $state('');
const options = [
{ value: 'apple', label: 'Apple' },
{ value: 'banana', label: 'Banana' },
{ value: 'orange', label: 'Orange' },
];
</script>
<Select {options} bind:value placeholder="Select a fruit" />Props
| Prop | Type | Default | Description |
|---|---|---|---|
value |
string |
'' |
Current selected value (bindable) |
options |
(SelectOption | SelectGroup)[] |
Required | Array of options or grouped options |
placeholder |
string |
'Select an option...' |
Placeholder text |
disabled |
boolean |
false |
Disables the select |
required |
boolean |
false |
Marks as required |
name |
string |
- | Name attribute for forms |
id |
string |
- | Element ID (auto-generated if empty) |
label |
string |
- | Label text |
hint |
string |
- | Hint text below the select |
error |
string |
- | Error message to display |
class |
string |
- | Additional CSS classes |
onValueChange |
(value: string) => void |
- | Callback when value changes |
searchable |
boolean | number |
false |
Type to narrow: true always, a number once there are that many options |
Types
interface SelectOption {
value: string;
label: string;
disabled?: boolean;
}
interface SelectGroup {
label: string;
options: SelectOption[];
}With Label and Hint
<Select label="Country" hint="Select your country of residence" {options} bind:value required />Or use the Label component for more control:
<script>
import { Select, Label } from '@classic-homes/theme-svelte';
</script>
<div class="space-y-2">
<Label for="country">Country</Label>
<Select id="country" {options} bind:value />
</div>Grouped Options
Organize options into logical groups:
<script>
const options = [
{
label: 'Fruits',
options: [
{ value: 'apple', label: 'Apple' },
{ value: 'banana', label: 'Banana' },
{ value: 'orange', label: 'Orange' },
],
},
{
label: 'Vegetables',
options: [
{ value: 'carrot', label: 'Carrot' },
{ value: 'broccoli', label: 'Broccoli' },
{ value: 'spinach', label: 'Spinach' },
],
},
];
</script>
<Select {options} bind:value placeholder="Select food" />Searchable
Long lists can narrow as you type. searchable renders a Combobox in place of the dropdown: true always, or a number to switch only once the options (counted across groups) reach that many. Short lists keep the plain dropdown.
<Select {options} bind:value label="Community" searchable={8} />Disabled Options
Disable individual options:
<script>
const options = [
{ value: 'available', label: 'Available' },
{ value: 'unavailable', label: 'Unavailable', disabled: true },
{ value: 'coming-soon', label: 'Coming Soon', disabled: true },
];
</script>
<Select {options} bind:value />States
Disabled
<Select {options} disabled value="apple" />Required
<Select {options} bind:value label="Required Field" required />With Error
<Select {options} bind:value label="Category" error="Please select a category" />Keyboard Navigation
The Select component supports full keyboard navigation:
| Key | Action |
|---|---|
Enter / Space |
Open dropdown / Select option |
Arrow Down |
Move to next option |
Arrow Up |
Move to previous option |
Home |
Move to first option |
End |
Move to last option |
Escape |
Close dropdown |
| Type characters | Typeahead to matching option |
Accessibility
The Select component includes:
- Proper ARIA attributes (
aria-label,aria-invalid) - Keyboard navigation support
- Focus management
- Screen reader announcements
- Typeahead search support
- Auto-generated IDs link labels to inputs
aria-describedbyconnects hint and error messages
Examples
Form Example
<script>
let department = $state('');
let departmentError = $state('');
const departments = [
{ value: 'sales', label: 'Sales' },
{ value: 'marketing', label: 'Marketing' },
{ value: 'engineering', label: 'Engineering' },
{ value: 'support', label: 'Support' },
];
function validate() {
if (!department) {
departmentError = 'Please select a department';
return false;
}
departmentError = '';
return true;
}
</script>
<Select
label="Department"
options={departments}
bind:value={department}
error={departmentError}
required
/>Controlled Select
<script>
let value = $state('');
function handleChange(newValue: string) {
console.log('Selected:', newValue);
value = newValue;
}
</script>
<Select {options} {value} onValueChange={handleChange} />Country Selector
<script>
const countries = [
{
label: 'North America',
options: [
{ value: 'us', label: 'United States' },
{ value: 'ca', label: 'Canada' },
{ value: 'mx', label: 'Mexico' },
],
},
{
label: 'Europe',
options: [
{ value: 'gb', label: 'United Kingdom' },
{ value: 'de', label: 'Germany' },
{ value: 'fr', label: 'France' },
],
},
];
</script>
<Select label="Country" options={countries} bind:value placeholder="Select your country" />Related Components
- Combobox - Select with search/filtering
- MultiSelect - Select multiple options
- RadioGroup - Radio buttons for fewer options