Select
Basic select
Basic select — see the example below.
import { Select } from "~/components/ui/base/select";
<Select.Root>
<Select.Label>Theme</Select.Label>
<Select.Trigger>
<Select.DisplayValue placeholder="Select an option" />
</Select.Trigger>
<Select.Popover>
<Select.Item value="light">
<Select.ItemLabel>Light</Select.ItemLabel>
<Select.ItemIndicator>✓</Select.ItemIndicator>
</Select.Item>
<Select.Item value="dark">
<Select.ItemLabel>Dark</Select.ItemLabel>
<Select.ItemIndicator>✓</Select.ItemIndicator>
</Select.Item>
</Select.Popover>
</Select.Root>
Align item with trigger vs popper
Analogous to Radix/shadcn: position="item-aligned" after opening shifts the panel so that the row with the current value (or highlighted item) is at the same height as the trigger; on a different choice the position is recomputed. position="popper" does not enforce this — it behaves like a standard floating menu. Both variants start with the initial value in the middle of the list (1–10).
item-aligned (default)
popper
import { component$ } from "@builder.io/qwik";
import { Select } from "~/components/ui/base/select";
export const ItemAlignCompare = component$(() => {
const items = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map((n) => (
<Select.Item key={n} value={String(n)}>
<Select.ItemLabel>{`Option ${n}`}</Select.ItemLabel>
</Select.Item>
));
return (
<div class="flex flex-wrap gap-10">
<div class="w-56 space-y-1">
<p class="text-caption-1 text-secondary-label">item-aligned (default)</p>
<Select.Root class="!max-w-none w-full" value="6">
<Select.Trigger>
<Select.DisplayValue placeholder="Select" />
</Select.Trigger>
<Select.Popover position="item-aligned">{items}</Select.Popover>
</Select.Root>
</div>
<div class="w-56 space-y-1">
<p class="text-caption-1 text-secondary-label">popper</p>
<Select.Root class="!max-w-none w-full" value="6">
<Select.Trigger>
<Select.DisplayValue placeholder="Select" />
</Select.Trigger>
<Select.Popover position="popper">{items}</Select.Popover>
</Select.Root>
</div>
</div>
);
});
Panel alignment (align)
The align prop on Select.Popover : start (default, matches bottom-start ), center , end . Here all examples use position="popper" so only the horizontal difference is visible. With a custom floating ending in -start / -end, align is not applied.
align="start" (default)
align="center"
align="end"
import { Select } from "~/components/ui/base/select";
// position="popper" disables vertical snapping to the selected item — shows purely horizontal align.
<div class="flex flex-wrap gap-8">
<div class="w-56 space-y-1">
<p class="text-caption-1 text-secondary-label">align="start" (default)</p>
<Select.Root class="!max-w-none w-full">
<Select.Trigger>
<Select.DisplayValue placeholder="Start" />
</Select.Trigger>
<Select.Popover position="popper" align="start">
<Select.Item value="a"><Select.ItemLabel>Ant</Select.ItemLabel></Select.Item>
<Select.Item value="b"><Select.ItemLabel>Bee</Select.ItemLabel></Select.Item>
</Select.Popover>
</Select.Root>
</div>
<div class="w-56 space-y-1">
<p class="text-caption-1 text-secondary-label">align="center"</p>
<Select.Root class="!max-w-none w-full">
<Select.Trigger>
<Select.DisplayValue placeholder="Center" />
</Select.Trigger>
<Select.Popover position="popper" align="center">
<Select.Item value="a"><Select.ItemLabel>Ant</Select.ItemLabel></Select.Item>
<Select.Item value="b"><Select.ItemLabel>Bee</Select.ItemLabel></Select.Item>
</Select.Popover>
</Select.Root>
</div>
<div class="w-56 space-y-1">
<p class="text-caption-1 text-secondary-label">align="end"</p>
<Select.Root class="!max-w-none w-full">
<Select.Trigger>
<Select.DisplayValue placeholder="End" />
</Select.Trigger>
<Select.Popover position="popper" align="end">
<Select.Item value="a"><Select.ItemLabel>Ant</Select.ItemLabel></Select.Item>
<Select.Item value="b"><Select.ItemLabel>Bee</Select.ItemLabel></Select.Item>
</Select.Popover>
</Select.Root>
</div>
</div>
Groups
Splitting items using Select.Group and GroupLabel (sections in the list).
import { Select } from "~/components/ui/base/select";
<Select.Root>
<Select.Trigger>
<Select.DisplayValue placeholder="Framework…" />
</Select.Trigger>
<Select.Popover>
<Select.Group>
<Select.GroupLabel>Popular</Select.GroupLabel>
<Select.Item value="qwik">
<Select.ItemLabel>Qwik</Select.ItemLabel>
</Select.Item>
</Select.Group>
<Select.Group>
<Select.GroupLabel>Other</Select.GroupLabel>
<Select.Item value="other">
<Select.ItemLabel>Other</Select.ItemLabel>
</Select.Item>
</Select.Group>
</Select.Popover>
</Select.Root>
Controlled value (bind:value)
Controlled value (bind:value) — see the example below.
Value: banana
import { component$, useSignal } from "@builder.io/qwik";
import { Select } from "~/components/ui/base/select";
export const Controlled = component$(() => {
const value = useSignal("banana");
return (
<>
<Select.Root bind:value={value}>
<Select.Trigger>
<Select.DisplayValue placeholder="Fruit" />
</Select.Trigger>
<Select.Popover>
<Select.Item value="apple">
<Select.ItemLabel>Apple</Select.ItemLabel>
</Select.Item>
<Select.Item value="banana">
<Select.ItemLabel>Banana</Select.ItemLabel>
</Select.Item>
</Select.Popover>
</Select.Root>
<p class="mt-2 text-caption-1 text-secondary-label">Value: {value.value}</p>
</>
);
});
Metadata
Source: meta.generated.json (see npm run generate)
File base/select/meta.generated.json not found or path not allowed.