Inputs
Select
Select — the Input's frame around a styled list of values.
import { Select } from 'omaris' Examples
Basic
Give it options and a label; the value is the option's value. For a short, fixed list nobody would search.
<script lang="ts"> import { Select } from 'omaris'; let city = $state('erbil'); const CITIES = [ { value: 'baghdad', label: 'Baghdad' }, { value: 'erbil', label: 'Erbil' }, { value: 'basra', label: 'Basra' }, { value: 'mosul', label: 'Mosul' } ];</script><Select class="w-64 max-w-full" label="City" options={CITIES} bind:value={city} /> Descriptions and groups
A description gives each row a second line and group puts rows under a heading — for a plan or a currency, where the name alone does not say enough.
<script lang="ts"> import { Select } from 'omaris'; let plan = $state('team'); const PLANS = [ { value: 'free', label: 'Free', description: 'One project', group: 'Personal' }, { value: 'pro', label: 'Pro', description: 'Unlimited projects', group: 'Personal' }, { value: 'team', label: 'Team', description: 'Up to 10 seats', group: 'Business' }, { value: 'enterprise', label: 'Enterprise', description: 'SSO and audit logs', group: 'Business' } ];</script><Select class="w-72 max-w-full" label="Plan" options={PLANS} bind:value={plan} /> States
The same states a text field has, wired the same way, so a form that mixes selects and text fields validates as one thing.
Choose a size.
<script lang="ts"> import { Select } from 'omaris'; const SIZES = [ { value: 's', label: 'Small' }, { value: 'm', label: 'Medium' }, { value: 'l', label: 'Large', disabled: true } ];</script><Select class="w-52 max-w-full" label="Required" required placeholder="Pick one" options={SIZES} /><Select class="w-52 max-w-full" label="Invalid" invalid placeholder="Pick one" supportingText="Choose a size." options={SIZES}/><Select class="w-52 max-w-full" label="Disabled" disabled value="m" options={SIZES} /><Select class="w-52 max-w-full" label="Clearable" clearable value="s" options={SIZES} /> Native
native renders a real <select>. It gives up the styled list and the descriptions, and gains the platform's own picker — which is what you want on a phone, and in a long form that has to feel native.
<script lang="ts"> import { Select } from 'omaris'; const YEARS = [ { value: '2020', label: '2020' }, { value: '2021', label: '2021' }, { value: '2022', label: '2022' }, { value: '2023', label: '2023' }, { value: '2024', label: '2024' }, { value: '2025', label: '2025' } ];</script><Select class="w-40 max-w-full" label="Styled" options={YEARS} value="2024" /><Select class="w-40 max-w-full" label="Native" native options={YEARS} value="2024" /> Overridden
A Select is a field with the shared popup list under it, so its parts are both sets — field is the closed control, option is a row of the list.
<script lang="ts"> import { Select } from 'omaris'; const CURRENCIES = [ { value: 'iqd', label: 'IQD' }, { value: 'usd', label: 'USD' }, { value: 'try', label: 'TRY' } ];</script><Select class="w-56 max-w-full" label="Currency" options={CURRENCIES} value="iqd" classes={{ value: 'font-mono tracking-wide', option: 'font-mono' }}/> When to use it
Use it for
- One value from a short, fixed list people already know: a currency, a plan, a region, a status.
- Rows that need more than a word:
descriptionfor a second line,iconfor a mark that carries into the field,groupfor headings. - A form on a phone, or a long native form.
nativeswaps the styled list for the platform's own picker.
Not for
- A list you would search rather than scroll (people, products, countries) → Combobox.
- Two to five choices that can stay visible → Segmented Button; a few choices that each need a line of explanation → Radio.
- Actions like rename, duplicate, delete → Menu. A Select holds a value; a Menu does something.
- Several values at once → filter Chips or a column of Checkboxes.
- On or off → Switch.
Do
- Give it a
placeholderwhile nothing is chosen, or avaluewhen one is obviously right, like the account's own currency. - Add
clearableonly when "none" is a valid answer, and say so insupportingText. - Split a list past a dozen rows with
group, so a currency list reads as regions. - Use
nativeon a phone form. The styled list is the desktop version.
Don't
- Use it for yes or no. That is a Switch or two Radios.
- Hide three options behind a closed field when they fit on the line. A Segmented Button shows them all.
- Rely on
descriptionoriconwithnative. The OS picker drops both, so the label must stand alone. - Pass
<option>children andoptionsat once. Children are for the native path only.
Quick reference
variant outline(default)filledghost
size smdefault(default)lg
API
Select
Select — the Input's frame around a styled list of values.
The list is drawn by the library, so it matches the rest of the UI in both themes, shows icons and descriptions, and can be navigated with arrows, Home/End and type-ahead while focus stays on the field. Pass native to get the OS picker instead — the one dropdown that always works on a phone.
For a list you search, use Combobox. For a menu of actions, Menu.
import { Select } from 'omaris' Parts
Every element this renders is reachable from outside. Pass Tailwind for one part as classes={{ part: '…' }}; class covers the root and is merged last, so it always wins.
root- No description in the source yet.
field- No description in the source yet.
control- The trigger, or the native
<select>: keeps its hit area, loses its chrome. value- No description in the source yet.
chevron- No description in the source yet.
adornment- No description in the source yet.
action- No description in the source yet.
label- No description in the source yet.
support- No description in the source yet.
placeholder- No description in the source yet.
surface- No description in the source yet.
option- No description in the source yet.
group- A non-interactive heading above a run of options.
body- No description in the source yet.
description- No description in the source yet.
check- No description in the source yet.
empty- "No results", "Searching…".
highlight- The part of a label that matched what was typed.
Props
variant Defaults to 'outline'
SelectVariant outlinefilledghost
size Defaults to 'default'
SelectSize smdefaultlg
value bindableDefaults to ''
string Selected value. Bindable.
options SelectOption[] Options to render. Omit and pass <option> children for a native select.
placeholder string Shown, greyed, while nothing is chosen.
label string required boolean Inside a Field, defaults to the field's.
supportingText string invalid boolean Inside a Field, defaults to the field's.
native Defaults to false
boolean Use the OS picker instead of the styled list.
mobileSheet boolean On a phone, the list rises from the bottom edge as a sheet — full width, a scrim behind, dragged down to dismiss, rows a thumb can hit — instead of hanging under the field. false keeps it anchored.
clearable Defaults to false
boolean Show an × that empties the field.
emptyText Defaults to 'No options'
string Text for an empty options array.
start Snippet Leading icon inside the frame.
option Snippet<[SelectOption, { selected: boolean; active: boolean }]> Custom row rendering for the styled list.
onchange (value: string, option: SelectOption | undefined) => void class string classes SelectClasses Per-part Tailwind overrides. class still covers the root.
children Snippet ref bindableDefaults to null
HTMLSelectElement | HTMLButtonElement | null