Select
Dropdown selector on bits-ui Select. The content springs open with a snappy scale-in, anchors to the trigger width, and the caret icon flips through color only — never layout.
Usage
select.svelte
<script lang="ts">
import { Select as SelectPrimitive } from 'bits-ui';
let {
open = $bindable(false),
value = $bindable(),
...restProps
}: SelectPrimitive.RootProps = $props();
</script>
<SelectPrimitive.Root
bind:open
bind:value={value as never}
{...restProps}
{...{ 'data-slot': 'select' } as Record<string, unknown>}
/>
Grouped options
select.svelte
<script lang="ts">
import { Select as SelectPrimitive } from 'bits-ui';
let {
open = $bindable(false),
value = $bindable(),
...restProps
}: SelectPrimitive.RootProps = $props();
</script>
<SelectPrimitive.Root
bind:open
bind:value={value as never}
{...restProps}
{...{ 'data-slot': 'select' } as Record<string, unknown>}
/>
Scrollable
Long option lists scroll inside a max-height constrained content panel.
select.svelte
<script lang="ts">
import { Select as SelectPrimitive } from 'bits-ui';
let {
open = $bindable(false),
value = $bindable(),
...restProps
}: SelectPrimitive.RootProps = $props();
</script>
<SelectPrimitive.Root
bind:open
bind:value={value as never}
{...restProps}
{...{ 'data-slot': 'select' } as Record<string, unknown>}
/>
States
select.svelte
<script lang="ts">
import { Select as SelectPrimitive } from 'bits-ui';
let {
open = $bindable(false),
value = $bindable(),
...restProps
}: SelectPrimitive.RootProps = $props();
</script>
<SelectPrimitive.Root
bind:open
bind:value={value as never}
{...restProps}
{...{ 'data-slot': 'select' } as Record<string, unknown>}
/>
Inverted
Set variant="inverted" on the content for a dark menu over
a light app — Bloom's signature menu identity. Surface and accent CSS vars swap at the content root,
so item rows, separators, and focus rings flip contrast automatically.
select-inverted.svelte
<Select.Root type="single" bind:value={theme}>
<Select.Trigger class="w-full">
<SelectPrimitive.Value placeholder="Theme" />
</Select.Trigger>
<Select.Content variant="inverted">
<Select.Item value="light" label="Light" />
<Select.Item value="dark" label="Dark" />
<Select.Item value="system" label="System" />
</Select.Content>
</Select.Root>Select.Root props
Inherits bits-ui Select.Root props via spread. Type must be set to discriminate single vs multiple selection.
| Prop | Type | Default | Description |
|---|---|---|---|
'single' | 'multiple' | — | Whether one value is selected at a time, or an array of values. | |
string | string[] (bindable) | — | Current selection. Two-way bindable. | |
boolean (bindable) | false | Whether the popover content is rendered. | |
boolean | false | Disables the whole control. | |
Array<{ value: string; label?: string; disabled?: boolean }> | — | Optional typeahead source. When omitted, typeahead still works against Select.Item labels. |
Select.Content props
Inherits bits-ui Select.Content props via spread.
| Prop | Type | Default | Description |
|---|---|---|---|
'default' | 'inverted' | 'default' | Surface treatment. Inverted swaps popover/accent CSS vars to render dark on light (and light on dark). | |
string | — | Merged onto the content surface via tailwind-merge. |
Select.Trigger props
Adds project-specific variant + size. Inherits bits-ui Select.Trigger props via spread.
| Prop | Type | Default | Description |
|---|---|---|---|
'bordered' | 'borderless' | 'bordered' | Visual weight. Borderless hugs toolbar buttons; bordered is the standalone form field. | |
'default' | 'sm' | 'default' | Controls trigger height via a data-size attribute. | |
'true' | 'false' | — | Flips the focus ring to destructive. | |
HTMLButtonElement | null | null | Two-way-bindable element reference. | |
string | — | Merged onto the trigger via tailwind-merge. |