<script lang="ts">
import { Select } from '$lib';
</script>
<div class="flex min-h-24 w-full items-center justify-center">
<div class="w-full max-w-xs space-y-2">
<Select
class="w-[200px]"
label="Favorite Fruit"
options={[{ label: 'Apple', value: 'apple' }, { label: 'Banana', value: 'banana' }, { label: 'Cherry', value: 'cherry' }]}
/>
</div>
</div> Installation
Barrel
import { Select } from 'kumo-svelte'; Granular
import { Select } from 'kumo-svelte/components/select';Usage
<script lang="ts"> import { Select } from 'kumo-svelte'; let value = $state('apple');</script><Select label="Favorite Fruit" bind:value items={{ apple: 'Apple', banana: 'Banana', cherry: 'Cherry' }}/>Examples
Basic
A select with a visible label. When you provide the label prop, the select automatically renders inside a Field wrapper with the label displayed above it.
<script lang="ts">
import { Select } from '$lib';
</script>
<div class="flex min-h-24 w-full items-center justify-center">
<div class="w-full max-w-xs space-y-2">
<Select
class="w-[200px]"
label="Favorite Fruit"
options={[{ label: 'Apple', value: 'apple' }, { label: 'Banana', value: 'banana' }, { label: 'Cherry', value: 'cherry' }]}
/>
</div>
</div> Sizes
Use the size prop
to match Input sizing (xs, sm, base, lg).
<script lang="ts">
import { Select } from '$lib';
const selectSizes = ['xs', 'sm', 'base', 'lg'] as const;
</script>
<div class="flex min-h-24 w-full items-center justify-center">
<div class="w-full max-w-xs space-y-2">
<div class="grid gap-4">
{#each selectSizes as selectSize (selectSize)}
<div class="flex items-center gap-3">
<span class="w-10 text-sm text-kumo-subtle">{selectSize}</span>
<Select aria-label={`Select size ${selectSize}`} size={selectSize} class="w-[200px]" placeholder="Choose..." options={[{ label: 'Option A', value: 'a' }, { label: 'Option B', value: 'b' }]} />
</div>
{/each}
</div>
</div>
</div> Without Visible Label
When a visible label isn't needed (e.g., in compact UIs or when context is clear),
use aria-label for accessibility.
<script lang="ts">
import { Select } from '$lib';
</script>
<div class="flex min-h-24 w-full items-center justify-center">
<div class="w-full max-w-xs space-y-2">
<Select
class="w-[200px]"
label="Favorite Fruit"
options={[{ label: 'Apple', value: 'apple' }, { label: 'Banana', value: 'banana' }, { label: 'Cherry', value: 'cherry' }]}
/>
</div>
</div> With Description and Error
Select integrates with the Field wrapper to show description text and validation errors.
<script lang="ts">
import { Select } from '$lib';
</script>
<div class="flex min-h-24 w-full items-center justify-center">
<div class="w-full max-w-xs space-y-2">
<Select
class="w-[200px]"
label="Favorite Fruit"
options={[{ label: 'Apple', value: 'apple' }, { label: 'Banana', value: 'banana' }, { label: 'Cherry', value: 'cherry' }]}
/>
</div>
</div> Placeholder
Use the placeholder prop
to show text when no value is selected. When using renderValue to
customize the display of selected values, the placeholder is shown instead of
calling renderValue when the value is null.
<script lang="ts"> import { Select } from 'kumo-svelte'; type User = { id: string; name: string }; const users: User[] = [ { id: 'visal', name: 'Visal' }, { id: 'alice', name: 'Alice' } ]; let user = $state('');</script><Select placeholder="Select a user..." bind:value={user} items={Object.fromEntries(users.map((user) => [user.id, user.name]))}/> <script lang="ts">
import { Select } from '$lib';
</script>
<div class="flex min-h-24 w-full items-center justify-center">
<div class="w-full max-w-xs space-y-2">
<Select
class="w-[200px]"
label="Favorite Fruit"
options={[{ label: 'Apple', value: 'apple' }, { label: 'Banana', value: 'banana' }, { label: 'Cherry', value: 'cherry' }]}
/>
</div>
</div> Label with Tooltip
Add a tooltip icon next to the label for additional context using labelTooltip.
<script lang="ts">
import { Select } from '$lib';
</script>
<div class="flex min-h-24 w-full items-center justify-center">
<div class="w-full max-w-xs space-y-2">
<Select
class="w-[200px]"
label="Favorite Fruit"
options={[{ label: 'Apple', value: 'apple' }, { label: 'Banana', value: 'banana' }, { label: 'Cherry', value: 'cherry' }]}
/>
</div>
</div> Custom Rendering
Use renderValue to customize how the selected value
appears in the trigger button. This is useful when working with complex object
data structures instead of simple string values.
<script lang="ts">
import { Select } from '$lib';
</script>
<div class="flex min-h-24 w-full items-center justify-center">
<div class="w-full max-w-xs space-y-2">
<Select
class="w-[200px]"
label="Favorite Fruit"
options={[{ label: 'Apple', value: 'apple' }, { label: 'Banana', value: 'banana' }, { label: 'Cherry', value: 'cherry' }]}
/>
</div>
</div> The renderValue function is only called when a value is selected. Use placeholder to define what to show when no value is selected.
<script lang="ts"> import { Select } from 'kumo-svelte'; const languages = [ { value: 'en', label: 'English', emoji: 'GB' }, { value: 'fr', label: 'French', emoji: 'FR' }, { value: 'de', label: 'German', emoji: 'DE' } ]; let value = $state('en');</script><Select class="w-[200px]" placeholder="Select a language..." bind:value items={languages.map((language) => ({ value: language.value, label: `${language.emoji} ${language.label}` }))}/>Loading
A select component with loading state. The loading state is passed to
the component via the loading prop.
<script lang="ts">
import { Select } from '$lib';
</script>
<div class="flex min-h-24 w-full items-center justify-center">
<div class="w-full max-w-xs space-y-2">
<Select
class="w-[200px]"
label="Favorite Fruit"
loading
options={[{ label: 'Apple', value: 'apple' }, { label: 'Banana', value: 'banana' }, { label: 'Cherry', value: 'cherry' }]}
/>
</div>
</div> Multiple Selection
Enable multiple selection with the multiple prop.
The value becomes an array of selected items. Use placeholder for the empty state
and renderValue to customize how selections are displayed.
<script lang="ts"> import { Select } from 'kumo-svelte'; let selectedColumns = $state(['name', 'email']);</script><Select multiple placeholder="Select columns..." bind:value={selectedColumns} renderValue={(columns) => columns.join(", ")} items={{ name: "Name", email: "Email" }}/> <script lang="ts">
import { Select } from '$lib';
</script>
<div class="flex min-h-24 w-full items-center justify-center">
<div class="w-full max-w-xs space-y-2">
<Select
class="w-[200px]"
label="Favorite Fruit"
options={[{ label: 'Apple', value: 'apple' }, { label: 'Banana', value: 'banana' }, { label: 'Cherry', value: 'cherry' }]}
/>
</div>
</div> More Example
<script lang="ts">
import { Select } from '$lib';
</script>
<div class="flex min-h-24 w-full items-center justify-center">
<div class="w-full max-w-xs space-y-2">
<Select
class="w-[200px]"
label="Favorite Fruit"
options={[{ label: 'Apple', value: 'apple' }, { label: 'Banana', value: 'banana' }, { label: 'Cherry', value: 'cherry' }]}
/>
</div>
</div> Disabled Options
Options can be disabled with the disabled prop.
Disabled options are greyed out and cannot be selected.
<script lang="ts">
import { Select } from '$lib';
</script>
<div class="flex min-h-24 w-full items-center justify-center">
<div class="w-full max-w-xs space-y-2">
<Select
class="w-[200px]"
label="Favorite Fruit"
disabled
options={[{ label: 'Apple', value: 'apple' }, { label: 'Banana', value: 'banana' }, { label: 'Cherry', value: 'cherry' }]}
/>
</div>
</div> Disabled Items (via items prop)
The items object-map prop
accepts descriptor objects with disabled alongside
plain string values.
<script lang="ts">
import { Select } from '$lib';
</script>
<div class="flex min-h-24 w-full items-center justify-center">
<div class="w-full max-w-xs space-y-2">
<Select
class="w-[200px]"
label="Favorite Fruit"
disabled
options={[{ label: 'Apple', value: 'apple' }, { label: 'Banana', value: 'banana' }, { label: 'Cherry', value: 'cherry' }]}
/>
</div>
</div> Grouped Options
Use Select.Group, Select.GroupLabel, and Select.Separator to
organize options under labeled headers with visual dividers.
<script lang="ts">
import { Select } from '$lib';
</script>
<div class="flex min-h-24 w-full items-center justify-center">
<div class="w-full max-w-xs space-y-2">
<Select
class="w-[200px]"
label="Favorite Fruit"
options={[{ label: 'Apple', value: 'apple' }, { label: 'Banana', value: 'banana' }, { label: 'Cherry', value: 'cherry' }]}
/>
</div>
</div> Groups with Disabled Options
Combine groups, separators, and disabled options with info tooltips to clearly separate available and unavailable choices.
<script lang="ts">
import { Select } from '$lib';
</script>
<div class="flex min-h-24 w-full items-center justify-center">
<div class="w-full max-w-xs space-y-2">
<Select
class="w-[200px]"
label="Favorite Fruit"
disabled
options={[{ label: 'Apple', value: 'apple' }, { label: 'Banana', value: 'banana' }, { label: 'Cherry', value: 'cherry' }]}
/>
</div>
</div> Long List (Scrolling Test)
A select component with many options to test popup scrolling behavior. The popup should scroll smoothly without bounce/overscroll issues.
<script lang="ts">
import { Select } from '$lib';
</script>
<div class="flex min-h-24 w-full items-center justify-center">
<div class="w-full max-w-xs space-y-2">
<Select
class="w-[200px]"
label="Favorite Fruit"
options={[{ label: 'Apple', value: 'apple' }, { label: 'Banana', value: 'banana' }, { label: 'Cherry', value: 'cherry' }]}
/>
</div>
</div> API Reference
Select
| Prop | Type | Default | Description |
|---|---|---|---|
| class | string | - | Additional classes merged onto the root element. |
| size | 'xs' | 'sm' | 'base' | 'lg' | "base" | Size preset. |
| label | string | Snippet | - | Visible label content. |
| hideLabel | boolean | false | hideLabel prop. |
| placeholder | string | "Select..." | Placeholder text. |
| loading | boolean | false | Loading state. |
| disabled | boolean | false | Disables the component. |
| required | boolean | false | Marks the field as required. |
| labelTooltip | string | Snippet | - | Optional help content for the label. |
| value | Value | - | Controlled value. |
| children | Snippet | - | Child snippet rendered by the component. |
| description | string | Snippet | - | Supporting description text. |
| error | FieldError | - | Validation error message or matcher. |
| defaultValue | Value | - | Initial uncontrolled value. |
| renderValue | (value: Value) => unknown | - | Custom selected-value renderer. |
| items | Record<string, SelectItemValue> | { label: Snippet | string; value: Value }[] | - | Items rendered by the component. |
| options | Option[] | [] | Options rendered by the component. |
| multiple | boolean | false | Enables multiple selection. |
| name | string | - | Form field name. |
| container | HTMLElement | string | - | Container element for the portal. |
Select.Option
| Prop | Type | Default | Description |
|---|---|---|---|
| size | 'xs' | 'sm' | 'base' | 'lg' | "base" | Size preset. |
| label | string | Snippet | - | Visible label content. |
| hideLabel | boolean | false | hideLabel prop. |
| placeholder | string | "Select..." | Placeholder text. |
| loading | boolean | false | Loading state. |
| disabled | boolean | false | Disables the component. |
| required | boolean | false | Marks the field as required. |
| labelTooltip | string | Snippet | - | Optional help content for the label. |
| value | Value | - | Controlled value. |
| description | string | Snippet | - | Supporting description text. |
| error | FieldError | - | Validation error message or matcher. |
| defaultValue | Value | - | Initial uncontrolled value. |
| renderValue | (value: Value) => unknown | - | Custom selected-value renderer. |
| items | Record<string, SelectItemValue> | { label: Snippet | string; value: Value }[] | - | Items rendered by the component. |
| options | Option[] | [] | Options rendered by the component. |
| multiple | boolean | false | Enables multiple selection. |
| name | string | - | Form field name. |
| container | HTMLElement | string | - | Container element for the portal. |
Select.Group
Groups related options together with an accessible role="group".
Use with Select.GroupLabel
to provide a visible heading.
Select.GroupLabel
A visible heading for a Select.Group.
Automatically associated with its parent group for accessibility.
Select.Separator
A visual divider line between option groups. Renders with role="separator".