Select
A dropdown component for selecting from a list of options
Basic Usage
Simple select with basic options.
Choose a fruit:
Code Svelte
1
2<script lang="ts">
3 import { Select, Badge } from "@kareyes/aether";
4
5 let basicValue = $state("");
6
7 const fruits = [
8 { value: "apple", label: "Apple" },
9 { value: "banana", label: "Banana" },
10 { value: "orange", label: "Orange" },
11 { value: "grape", label: "Grape" },
12 { value: "strawberry", label: "Strawberry" }
13 ];
14</script>
15
16<Select
17 bind:value={basicValue}
18 options={fruits}
19 placeholder="Select a fruit..."
20 class="w-[200px]"
21 onSelectionChange={(value) => console.log('Selected:', value)}
22/>
23{#if basicValue}
24 <p class="text-sm text-muted-foreground mt-2">
25 Selected: <Badge variant="secondary">{basicValue}</Badge>
26 </p>
27{/if}Multiple Selection
Allow users to select multiple options at once.
Choose multiple frameworks:
Code Svelte
1
2<script lang="ts">
3 import { Select, Badge } from "@kareyes/aether";
4
5 let multiValue = $state<string[]>([]);
6
7 const frameworks = [
8 { value: "react", label: "React" },
9 { value: "vue", label: "Vue.js" },
10 { value: "svelte", label: "Svelte" },
11 { value: "angular", label: "Angular" },
12 { value: "solid", label: "SolidJS" }
13 ];
14</script>
15
16<Select
17 bind:value={multiValue}
18 options={frameworks}
19 multiple={true}
20 placeholder="Select frameworks..."
21 class="w-[250px]"
22/>
23{#if multiValue.length > 0}
24 <div class="flex flex-wrap gap-2 mt-2">
25 {#each multiValue as item}
26 <Badge variant="secondary">{item}</Badge>
27 {/each}
28 </div>
29{/if}Grouped Options
Organize options into labeled groups.
Choose a framework:
Code Svelte
1
2<script lang="ts">
3 import { Select, Badge } from "@kareyes/aether";
4
5 let groupedValue = $state("");
6
7 const groupedOptions = [
8 {
9 label: "Frontend Frameworks",
10 options: [
11 { value: "react", label: "React" },
12 { value: "vue", label: "Vue.js" },
13 { value: "svelte", label: "Svelte" },
14 { value: "angular", label: "Angular" }
15 ]
16 },
17 {
18 label: "Backend Frameworks",
19 options: [
20 { value: "express", label: "Express.js" },
21 { value: "fastify", label: "Fastify" },
22 { value: "koa", label: "Koa.js" },
23 { value: "nestjs", label: "NestJS" }
24 ]
25 }
26 ];
27</script>
28
29<Select
30 bind:value={groupedValue}
31 groups={groupedOptions}
32 placeholder="Select a framework..."
33 class="w-[250px]"
34/>
35{#if groupedValue}
36 <p class="text-sm text-muted-foreground mt-2">
37 Selected: <Badge variant="secondary">{groupedValue}</Badge>
38 </p>
39{/if}Error States
Validation error display with select components.
This field is required
Please make a selection
Large Error Select
Invalid selection
Code Svelte
1
2<script lang="ts">
3 import { Select, Field } from "@kareyes/aether";
4</script>
5
6<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
7 <Field
8 label="Username"
9 description="Choose a unique username for your account."
10 required
11 error={"This field is required"}
12 >
13 <Select
14 options={fruits}
15 placeholder="Select a fruit..."
16 class="w-full"
17 error={true}
18 />
19 </Field>
20
21 <Field
22 label="Outline with Error"
23 error={"Please make a selection"}
24 required
25 >
26 <Select
27 options={frameworks}
28 variant="outline"
29 placeholder="Select framework..."
30 class="w-full"
31 error={true}
32 />
33 </Field>
34</div>Variants
Available visual styles for the select component.
Default
Outline
Filled
Ghost
Underline
Code Svelte
1
2<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
3 <div>
4 <span class="block text-sm font-medium mb-2">Default</span>
5 <Select options={fruits} variant="default" placeholder="Default variant" class="w-full" />
6 </div>
7
8 <div>
9 <span class="block text-sm font-medium mb-2">Outline</span>
10 <Select options={fruits} variant="outline" placeholder="Outline variant" class="w-full" />
11 </div>
12
13 <div>
14 <span class="block text-sm font-medium mb-2">Filled</span>
15 <Select options={fruits} variant="filled" placeholder="Filled variant" class="w-full" />
16 </div>
17
18 <div>
19 <span class="block text-sm font-medium mb-2">Ghost</span>
20 <Select options={fruits} variant="ghost" placeholder="Ghost variant" class="w-full" />
21 </div>
22
23 <div>
24 <span class="block text-sm font-medium mb-2">Underline</span>
25 <Select options={fruits} variant="underline" placeholder="Underline variant" class="w-full" />
26 </div>
27</div>Sizes
Different size options for the select component.
Small
Default
Large
Code Svelte
1
2<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
3 <div>
4 <span class="block text-sm font-medium mb-2">Small</span>
5 <Select options={fruits} size="sm" placeholder="Small size" class="w-full" />
6 </div>
7
8 <div>
9 <span class="block text-sm font-medium mb-2">Default</span>
10 <Select options={fruits} size="default" placeholder="Default size" class="w-full" />
11 </div>
12
13 <div>
14 <span class="block text-sm font-medium mb-2">Large</span>
15 <Select options={fruits} size="lg" placeholder="Large size" class="w-full" />
16 </div>
17</div>States
Normal and disabled select states.
Normal
Disabled
Code Svelte
1
2<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
3 <div>
4 <span class="block text-sm font-medium mb-2">Normal</span>
5 <Select options={fruits} placeholder="Normal state" class="w-full" />
6 </div>
7
8 <div>
9 <span class="block text-sm font-medium mb-2 text-muted-foreground">Disabled</span>
10 <Select options={fruits} disabled={true} placeholder="Disabled state" class="w-full" />
11 </div>
12</div>Disabled Options
Individual options can be disabled within the select.
Some options disabled:
Code Svelte
1
2<Select
3 options={[
4 { value: "apple", label: "Apple" },
5 { value: "banana", label: "Banana", disabled: true },
6 { value: "orange", label: "Orange" },
7 { value: "grape", label: "Grape", disabled: true },
8 { value: "strawberry", label: "Strawberry" }
9 ]}
10 placeholder="Try to select..."
11 class="w-[200px]"
12/>Basic Usage
<script lang="ts">
import { Select } from "@kareyes/aether";
let value = $state("");
const options = [
{ value: "apple", label: "Apple" },
{ value: "banana", label: "Banana" },
{ value: "orange", label: "Orange" }
];
</script>
<Select
bind:value
{options}
placeholder="Select a fruit..."
class="w-[200px]"
/>
With Primitives Import
<script lang="ts">
import { SelectPrimitives } from "@kareyes/aether";
</script>
<SelectPrimitives.Root bind:value>
<SelectPrimitives.Trigger class="w-[200px]">
<SelectPrimitives.Value placeholder="Select..." />
</SelectPrimitives.Trigger>
<SelectPrimitives.Content>
<SelectPrimitives.Item value="apple">Apple</SelectPrimitives.Item>
<SelectPrimitives.Item value="banana">Banana</SelectPrimitives.Item>
</SelectPrimitives.Content>
</SelectPrimitives.Root>
Props Reference
| Prop | Type | Default | Description |
|---|---|---|---|
value |
string | string[] | undefined |
undefined |
The selected value(s). Use bind:value for two-way binding |
options |
SelectOption[] |
[] |
Array of options for the select |
groups |
SelectGroup[] |
[] |
Array of grouped options |
multiple |
boolean |
false |
Whether multiple selections are allowed |
disabled |
boolean |
false |
Whether the entire select is disabled |
required |
boolean |
false |
Whether the select is required |
placeholder |
string |
"Select an option..." |
Placeholder text |
variant |
SelectVariant |
"default" |
Visual variant |
size |
SelectSize |
"default" |
Size variant |
name |
string |
undefined |
Name attribute for form submission |
class |
string |
- | Additional CSS classes |
triggerClass |
string |
- | Classes for the trigger element |
contentClass |
string |
- | Classes for the dropdown content |
itemClass |
string |
- | Classes for individual items |
sideOffset |
number |
4 |
Offset distance from the trigger |
error |
boolean |
false |
Error state with visual feedback |
onSelectionChange |
(value) => void |
- | Callback when selection changes |
Types
interface SelectOption {
value: string;
label: string;
disabled?: boolean;
}
interface SelectGroup {
label?: string;
options: SelectOption[];
}
type SelectVariant = "default" | "outline" | "filled" | "ghost" | "underline";
type SelectSize = "sm" | "default" | "lg";
Variants
All Variants
<Select {options} variant="default" />
<Select {options} variant="outline" />
<Select {options} variant="filled" />
<Select {options} variant="ghost" />
<Select {options} variant="underline" />
Sizes
<Select {options} size="sm" />
<Select {options} size="default" />
<Select {options} size="lg" />
Examples
Multiple Selection
<script lang="ts">
import { Select } from "@kareyes/aether";
let selectedFrameworks = $state<string[]>([]);
const frameworks = [
{ value: "react", label: "React" },
{ value: "vue", label: "Vue.js" },
{ value: "svelte", label: "Svelte" }
];
</script>
<Select
bind:value={selectedFrameworks}
options={frameworks}
multiple={true}
placeholder="Select frameworks..."
class="w-[250px]"
/>
Grouped Options
<script lang="ts">
import { Select } from "@kareyes/aether";
let selectedFramework = $state("");
const groups = [
{
label: "Frontend Frameworks",
options: [
{ value: "react", label: "React" },
{ value: "vue", label: "Vue.js" },
{ value: "svelte", label: "Svelte" }
]
},
{
label: "Backend Frameworks",
options: [
{ value: "express", label: "Express.js" },
{ value: "fastify", label: "Fastify" },
{ value: "nestjs", label: "NestJS" }
]
}
];
</script>
<Select
bind:value={selectedFramework}
{groups}
placeholder="Select a framework..."
class="w-[250px]"
/>
Disabled States
<!-- Disabled component -->
<Select {options} disabled={true} />
<!-- Some options disabled -->
<Select
options={[
{ value: "apple", label: "Apple" },
{ value: "banana", label: "Banana", disabled: true },
{ value: "orange", label: "Orange" }
]}
/>
Selection Change Callback
<script lang="ts">
import { Select } from "@kareyes/aether";
function handleSelectionChange(value: string) {
console.log('Selection changed:', value);
}
</script>
<Select
{options}
onSelectionChange={handleSelectionChange}
/>
With Field Component
<script lang="ts">
import { Field, Select } from "@kareyes/aether";
let country = $state('');
const countries = [
{ value: 'us', label: 'United States' },
{ value: 'uk', label: 'United Kingdom' },
{ value: 'ca', label: 'Canada' },
];
</script>
<Field
label="Country"
description="Select your country of residence"
required
>
<Select
bind:value={country}
options={countries}
placeholder="Select a country..."
/>
</Field>
With Validation
<script lang="ts">
import { Field, Select } from "@kareyes/aether";
let framework = $state('');
let errors = $state<Record<string, string>>({});
const frameworks = [
{ value: 'react', label: 'React' },
{ value: 'vue', label: 'Vue.js' },
{ value: 'svelte', label: 'Svelte' },
];
function validate() {
if (!framework) {
errors.framework = 'Please select a framework';
} else {
delete errors.framework;
}
}
</script>
<Field
label="Framework"
description="Choose your preferred framework"
required
error={errors.framework}
>
<Select
bind:value={framework}
options={frameworks}
placeholder="Select framework..."
error={!!errors.framework}
onSelectionChange={validate}
/>
</Field>
Complete Form Example
<script lang="ts">
import { Field, Select, Button } from "@kareyes/aether";
let formData = $state({
country: '',
framework: '',
languages: [] as string[],
});
let errors = $state<Record<string, string>>({});
const countries = [
{ value: 'us', label: 'United States' },
{ value: 'uk', label: 'United Kingdom' },
];
const frameworks = [
{ value: 'react', label: 'React' },
{ value: 'vue', label: 'Vue.js' },
{ value: 'svelte', label: 'Svelte' },
];
const languages = [
{ value: 'js', label: 'JavaScript' },
{ value: 'ts', label: 'TypeScript' },
{ value: 'python', label: 'Python' },
];
function handleSubmit(e: Event) {
e.preventDefault();
errors = {};
if (!formData.country) errors.country = 'Country is required';
if (!formData.framework) errors.framework = 'Framework is required';
if (formData.languages.length === 0) {
errors.languages = 'Select at least one language';
}
if (Object.keys(errors).length === 0) {
console.log('Form submitted:', formData);
}
}
</script>
<form onsubmit={handleSubmit} class="space-y-6">
<Field
label="Country"
required
error={errors.country}
>
<Select
bind:value={formData.country}
options={countries}
placeholder="Select country..."
error={!!errors.country}
/>
</Field>
<Field
label="Framework"
required
error={errors.framework}
>
<Select
bind:value={formData.framework}
options={frameworks}
placeholder="Select framework..."
error={!!errors.framework}
/>
</Field>
<Field
label="Languages"
required
error={errors.languages}
>
<Select
bind:value={formData.languages}
options={languages}
multiple={true}
placeholder="Select languages..."
error={!!errors.languages}
/>
</Field>
<Button type="submit">Save Profile</Button>
</form>
Accessibility
The Select component follows accessibility best practices:
Keyboard Navigation
| Key | Action |
|---|---|
Enter / Space |
Open dropdown or select item |
Arrow Down |
Move to next item |
Arrow Up |
Move to previous item |
Escape |
Close dropdown |
Home |
Move to first item |
End |
Move to last item |
Best Practices
- Provide labels: Always use with Field component for proper labeling
- Placeholder text: Use descriptive placeholder text
- Error states: Use
errorprop for validation feedback - Disabled states: Clearly indicate disabled options