Select

A native dropdown for choosing one option from a list.

import { ... } from '@corndev/ui'

HTML

<label class="corn-label" for="plan">Plan</label>
<select id="plan" class="corn-select" data-size="md">
  <option>Choose…</option>
</select>

Classes

Class
.corn-select

Attributes

AttributeValues
data-sizesm|md|lg
data-errorpresent or absent
data-full-widthpresent or absent

Vanilla JS

Required for behaviour — adds given options, builds the entries from data and reports the chosen value as given — a number as a number, null for the empty entry — rather than as a string.

import { createSelect } from '@corndev/ui';
import '@corndev/ui/theme';

const el = document.querySelector('#target');
const instance = createSelect(el, { /* options */ });

Options

OptionTypeDefaultDescription
optionsArray<SelectOption|SelectGroup|string|number>undefinedBuild the <option>s from data, replacing the element’s own: strings, numbers, { label, value, disabled }, or { group, items } as <optgroup>. Values are compared with ===. Without it, the element’s markup is left alone.
value*undefinedThe chosen value, with options. null — or '', unless an option has that value — selects the empty entry, which is there whenever the value is null. A value the list does not contain is shown as its own entry, marked “(not in the list)”, rather than as whichever option happens to be first. Pass it to update() to set the value from outside.
onChange(value: *, option: SelectOption|null) => voidundefinedWith options: called with the chosen value and its option, or null, null for the empty entry — the value as given, a number as a number.
placeholderstringundefinedWith options: an empty first entry showing this text, selected while the value is null. It cannot be chosen back unless clearable.
clearablebooleanfalseWith options: the empty entry can be chosen, returning the field to null. Without a placeholder it reads blank.
size'sm'|'md'|'lg''md'
disabledbooleanfalse
errorbooleanfalse
fullWidthbooleanfalse

React

Select — from @corndev/ui-react.

Props

PropTypeDefaultDescription
optionsArray<SelectOption|SelectGroup|string|number>undefinedThe choices, in place of children: strings, numbers, { label, value, disabled }, or { group, items }. Values are compared with ===.
value*undefinedThe chosen value (controlled), with options. null — or '', unless an option has that value — selects the empty entry, which is there whenever the value is null. A value the list does not contain is shown as its own entry, marked “(not in the list)”, rather than as whichever option happens to be first.
defaultValue*undefinedInitially chosen (uncontrolled), with options.
onChange((value: *, option: SelectOption|null) => void) | React.ChangeEventHandler<HTMLSelectElement>undefinedWith options: called with the chosen value and its option, or null, null for the empty entry. With children: the native change event.
placeholderstringundefinedWith options: an empty first entry showing this text, selected while the value is null. It cannot be chosen back unless clearable.
clearablebooleanfalseWith options: the empty entry can be chosen, returning the field to null. Without a placeholder it reads blank.
size'sm'|'md'|'lg''md'
disabledbooleanfalse
errorbooleanfalse
fullWidthbooleanfalse
childrenReact.ReactNodeundefinedOption elements, when not using options.
classNamestringundefined

Default

<Label htmlFor="plan">Plan</Label>
<Select id="plan">
  <option value="">Choose an option</option>
  <option value="a">Option A</option>
  <option value="b">Option B</option>
</Select>

Sizes

<Select size="sm" aria-label="Small">...</Select>
<Select size="md" aria-label="Medium">...</Select>
<Select size="lg" aria-label="Large">...</Select>

Error state

<Select error aria-label="Plan">...</Select>

Disabled

<Select disabled aria-label="Plan">...</Select>

Full width

<Select fullWidth aria-label="Plan">...</Select>

From data

Pass options instead of children — the same shapes as Combobox and SegmentedControl, so one list can feed any of them:

<Select
  aria-label="Type"
  options={['any', { label: 'Integer', value: 1 }, { group: 'Text', items: ['string', 'uuid'] }]}
  placeholder="Choose a type"
  clearable
  value={type}
  onChange={setType}
/>
  • onChange receives the value, as given — 1 comes back as the number 1, not the string a <select> reports — and the option it came from. With children, onChange is still the native event.
  • Groups render as <optgroup>, and { disabled: true } disables one entry.
  • The field always shows the value it holds. While the value is null there is an empty first entry — placeholder gives it text — which cannot be chosen back unless the field is clearable. A value the list does not contain is shown as its own entry, marked “(not in the list)”, rather than as whichever option comes first — a <select> left to itself shows the first option either way.
  • clearable lets the empty entry be chosen, which calls onChange(null, null) — null, not '', so a document field is cleared rather than set to an empty string.

It is still a native <select>: the browser’s own list, keyboard and form submission, where each option submits its value as text.