Select

A trigger that opens a list of options to pick a single value from.

Usage

import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from '@epilot/spark-ui/select'
<Select items={items}>
  <SelectTrigger>
    <SelectValue placeholder="Pick one" />
  </SelectTrigger>
  <SelectContent>
    <SelectItem value="a">Option A</SelectItem>
  </SelectContent>
</Select>

SelectValue renders the raw value by default. Pass items (a { value, label } list) on the root, or a children formatter, so it shows a label instead.

Examples

Groups

Wrap related options in SelectGroup with a SelectLabel, and split sections with SelectSeparator. Mark unavailable options disabled.

Input styles

The trigger is themed as an input box: it reads data-input-style (soft / surface / outlined / ghost) and data-input-color (brand / gray) from the enclosing <Field> or <Theme>, so a Select and an Input look identical in the same form. Override per instance with variant.

With a label

Compose inside <Field> to get a label with the same positions as any field: outset (above), inset (inside the shell). The trigger picks up the field's id, inputStyle, and aria-describedby, and goes bare in inset so the shell carries the box.

Hidden label

Pass srOnly to FieldLabel to hide it visually while keeping it in the accessibility tree; it still names and focuses the control. Prefer this over dropping the label when the surrounding UI already makes the purpose obvious.

Disabled

Set disabled on the root to disable the whole control.

Clearing a selection

Base UI ships no Select.Clear, so SelectClear is a plain button that sits beside the trigger inside SelectTriggerGroup rather than nesting inside it. The group hides the clear button while the trigger shows its placeholder, is disabled, or is read-only. Select must be controlled (value + onValueChange) so the app can reset the value itself. Clicking or activating the clear button returns keyboard focus to the trigger.

multiple works the same way; clear to an empty array.

API Reference

Built on Base UI Select. See the Base UI docs for the full API (value, defaultValue, items, multiple, onValueChange, …). Spark notes:

  • SelectTrigger is themed as an input box aligned with Input: resolves inputStyle / inputColor from the enclosing Field / Theme (shared box recipes), with a variant prop ("soft" | "surface" | "outlined" | "ghost") to override; size: "sm" | "default"; follows the radius knob; picks up the Field id + aria-describedby when inside one.
  • SelectContent renders its own portal; drops below the trigger like a popover by default, matching its width. Set alignItemWithTrigger to overlay the menu on the trigger (aligning the selected item over it) instead; height-capped and scrollable. Pass container to mount the portal into a different document/element than document.body — an embedded preview iframe, say.
  • SelectValue: pass items on the root or a children formatter to render a label rather than the raw value.
  • SelectTriggerGroup wraps SelectTrigger and SelectClear as siblings and hides the clear button while the trigger is a placeholder, disabled, or read-only. className="w-full" makes it span a Field the same way the trigger does on its own.
  • SelectClear is a plain <button> that resets keyboard focus to the trigger after your onClick runs — wire onClick to reset your controlled value (null, or [] for multiple). Pass aria-label; the default icon is decorative.

Accessibility

  • The trigger is a native <button> with role="combobox". Arrow keys move the highlight in the popup, Enter/Space chooses the highlighted option, Escape closes it.
  • Name the trigger with a FieldLabel or aria-label.
  • SelectClear needs its own aria-label — the same rule as AutocompleteClear.

On this page