Skip to content

Select ​

The form dropdown — a closed trigger showing the current value, a panel of options on click. Nearly always you want SimpleSelect: hand it an items array and it builds the whole thing. Reach for the compound parts only when an option row needs markup of its own, like a unit symbol or a status dot next to the label.

ts
import { Select, SelectTrigger, SelectContent, SelectItem, SelectValue, SimpleSelect } from '@scaler-tech/aurora/select'

SimpleSelect

Collection frequency: monthly

Missing value

A required field left empty — missing colors the border and adds the marker icon.

Multiple

Emission scopes: scope-1

Popper

position="popper" drops the panel below the trigger at trigger width instead of overlaying it.

Custom option rows

Energy unit: —

Use when ​

SituationUseWhy
Pick one value in a form, options are plain labelsSimpleSelectone array, no template
Same, but rows carry icons, tags, or secondary textSelect + partsthe row is your markup
The list is long enough that typing to narrow it matters, plain labelsSimpleComboboxone array, search over the labels
Same, but rows need custom markup or groupingCombobox + partstext input plus filtering, the row is your markup
Filtering wanted, but not inside a form — a popover or sidebar listListboxnot a form element, no field chrome
Few options that should all stay visibleSegmentedControlthe options are the UI
A pill in the filter row above a tableFilterTrigger + FilterPanelfilter chrome, not field chrome

API ​

SimpleSelect ​

Forwards every SelectRootProps prop and emit through to reka's SelectRoot, so v-model, multiple, defaultValue, by, name, and required all work. The ones you reach for:

PropTypeDefaultDescription
v-modelstring | number—Selected value; matches an item's value — numeric ids stay numbers
items{ value: string | number, label: string, disabled?: boolean }[]—Required, rendered in array order
placeholderstring''Trigger text while nothing is selected
position'popper' | 'item-aligned''item-aligned'Passed to SelectContent; see the compound table below
multiplebooleanfalsev-model becomes an array; the trigger joins labels with ,
validationFormStateProps—error / warning / success / missing / disabled / readonly booleans; the first four color the border and add an icon

Its panel carries an inline z-index: 100000, which no class can lower — the compound form's z-9999 is what you drop to if a select ever has to sit under something.

Compound parts ​

ComponentPropTypeDefaultDescription
Select—SelectRootProps & FormStateProps—State only; renders no element
SelectTriggerclassstring—Merged over the field styling; where you put the width
SelectValueplaceholderstring''Shown until something is selected
SelectContentposition'popper' | 'item-aligned''item-aligned'item-aligned overlays the trigger so the selected row lands where the trigger was (native macOS select); the panel sizes itself from reka's inline styles and shows scroll buttons when it overflows. popper drops the panel below the trigger at trigger width, like Combobox
SelectContentbodyLockbooleanfalseAurora overrides reka's default; the page behind stays scrollable
SelectItemvaluestring—Required
SelectItemdisabledbooleanfalseDimmed, not selectable
SelectItemtextValuestring—Overrides the scraped label used by the trigger and typeahead

Example ​

vue
<SimpleSelect v-model="frequency" :items="frequencies" placeholder="Pick a frequency" />

<Select v-model="unit">
    <SelectTrigger>
        <SelectValue placeholder="Pick a unit" />
    </SelectTrigger>
    <SelectContent>
        <SelectItem v-for="u in units" :key="u.value" :value="u.value" :text-value="u.label" class="pr-8">
            {{ u.label }}
            <span class="text-secondary ml-2">{{ u.symbol }}</span>
        </SelectItem>
    </SelectContent>
</Select>

Incorrect / Correct ​

Incorrect (four compound parts to render plain labels — SimpleSelect is the same dropdown):

vue
<Select v-model="frequency">
    <SelectTrigger>
        <SelectValue :placeholder="translate('automations.select-frequency')" />
    </SelectTrigger>
    <SelectContent>
        <SelectItem v-for="f in frequencies" :key="f.value" :value="f.value">
            {{ f.label }}
        </SelectItem>
    </SelectContent>
</Select>

Correct (the wrapper renders exactly that tree, and keeps the panel above modals):

vue
<SimpleSelect
    v-model="frequency"
    :items="frequencies"
    :placeholder="translate('automations.select-frequency')"
/>

Gotchas ​

  • A class on SimpleSelect or Select is silently dropped, so class="w-24" leaves a full-width dropdown — put the width on a wrapper div, or on SelectTrigger.
  • Validation props survive that same hop only because Select merges them onto its first non-comment child — wrap the trigger in a div and error stops arriving.
  • Markup inside SelectItem is flattened into the trigger label, so a muted "kWh" hint reappears as Kilowatt hours kWh when closed — pass text-value with the clean label, and pr-8 on the item so long labels clear the selected row's checkmark. [external]
  • Content inside <SelectValue> pins that content: the selected label never renders and the placeholder never shows. Leave it empty unless you want a fixed trigger label.
  • Combobox — the same picker with a filter input, for long lists; SimpleCombobox is the one-line form
  • Listbox — a filterable list outside form chrome
  • Segmented control — few options, all visible at once
  • Filter — pill triggers and panels for the filter row above a table