Select
A single-choice dropdown built on a real button and a portalled listbox panel, with full keyboard navigation, typeahead and focus that never leaves the trigger.
Preview
<script lang="ts">
import { Select } from "fancy-ui-svelte";
const frameworks = [
{ value: "svelte", label: "Svelte 5" },
{ value: "react", label: "React" },
{ value: "vue", label: "Vue" },
];
let framework = $state("svelte");
</script>
<Select
options={frameworks}
bind:value={framework}
label="Framework"
placeholder="Choose a framework"
class="w-[220px]"
/>Installation
Usage
<script lang="ts">
import { Select } from 'fancy-ui-svelte';
</script>
<Select />Examples
Basic Usage
Three frameworks, one selected by default.
<script lang="ts">
import { Select } from "$lib/fancy-ui/select";
const frameworks = [
{ value: "svelte", label: "Svelte 5" },
{ value: "react", label: "React" },
{ value: "vue", label: "Vue" },
];
let framework = $state("svelte");
</script>
<Select
options={frameworks}
bind:value={framework}
label="Framework"
placeholder="Choose a framework"
class="w-[220px]"
/>With FormField
Wrapped in FormField — required and the error message driven by context.
<script lang="ts">
import { FormField } from "$lib/fancy-ui/form-field";
import { Select } from "$lib/fancy-ui/select";
const plans = [
{ value: "starter", label: "Starter" },
{ value: "team", label: "Team" },
{ value: "enterprise", label: "Enterprise" },
];
let plan = $state("");
</script>
<FormField label="Plan" required error={plan === "" ? "Choose a plan to continue." : undefined}>
<Select options={plans} bind:value={plan} placeholder="Select a plan" class="w-[220px]" />
</FormField>Disabled Options
One option unavailable — skipped by keyboard, typeahead and pointer selection.
<script lang="ts">
import { Select } from "$lib/fancy-ui/select";
const regions = [
{ value: "us", label: "United States" },
{ value: "eu", label: "Europe" },
{ value: "ap", label: "Asia Pacific (coming soon)", disabled: true },
];
let region = $state("us");
</script>
<Select options={regions} bind:value={region} label="Region" class="w-[240px]" />Placement
The panel anchored on all four sides of the trigger.
<script lang="ts">
import { Select } from "$lib/fancy-ui/select";
const sizes = [
{ value: "sm", label: "Small" },
{ value: "md", label: "Medium" },
{ value: "lg", label: "Large" },
];
const sides = ["top", "right", "bottom", "left"] as const;
</script>
<div class="flex flex-wrap items-center gap-6">
{#each sides as side (side)}
<Select options={sizes} placeholder={side} {side} class="w-[140px]" />
{/each}
</div>Props
| Prop | Type | Default | Description |
|---|---|---|---|
options * | SelectOption[] | - | The choices, in order — { value, label, disabled? }. |
value | string | "" | The selected value, bindable — "" means nothing is selected. |
onValueChange | (value: string) => void | - | Called with the new value whenever the selection changes. |
placeholder | string | - | Shown in the trigger while nothing is selected. |
disabled | boolean | false | Blocks opening; excludes the control from form submission. |
required | boolean | false | Marks the control required (aria-required). No native form-validation enforcement — see the README. |
invalid | boolean | false | Drives the error border and aria-invalid. |
id | string | - | Element id. |
name | string | - | Native name. When set, a hidden input carries the value into the form. |
label | string | - | Accessible name — for a control with no visible Label next to it. |
side | "top" | "bottom" | "left" | "right" | "bottom" | Side of the trigger to place the panel on. Flips when it would overflow. |
align | "start" | "center" | "end" | "start" | Alignment along the trigger's cross axis. |
class | string | - | Additional CSS classes, merged onto the trigger. |
ref | HTMLButtonElement | null | null | Bindable reference to the trigger button. |
sound | boolean | false | Plays open on opening, select on a committed choice and close on a dismissal, once the user has enabled sound |
Links
Related components
Autocomplete
A free-text field with a portalled panel of matching suggestions — any typed value is valid; the panel only ever helps finish it faster.
Checkbox
A tri-look checkbox — unchecked, checked, indeterminate and disabled — built on a native checkbox input
Combobox
A single-choice text field over a closed set of options — typing filters a portalled listbox, and a value outside the list can never be selected.