Select

Molecule

Label + select + hint + error anatomy. appearance-none overrides the native dropdown style and renders a chevron icon.

Props EditorInteractive
<Select id="role" label="Role"
  options={[{ value: 'admin', label: 'Admin' }, ...]}
/>

Controlled

Preview

Selected: Editor

Code
const ROLES = [
  { value: 'admin', label: 'Admin' },
  { value: 'editor', label: 'Editor' },
  { value: 'viewer', label: 'Viewer' },
];

const [role, setRole] = useState('editor');
<Select id="role" label="Role" options={ROLES} value={role}
  onChange={(e) => setRole(e.target.value)} />

With icons

Preview
Code
const STATUSES = [
  { value: 'active',   label: 'Active',   icon: <span className="text-success">●</span> },
  { value: 'inactive', label: 'Inactive', icon: <span className="text-text-disabled">●</span> },
  { value: 'pending',  label: 'Pending',  icon: <span className="text-warning">●</span> },
];

<Select id="status" label="Status" options={STATUSES} value={status} onChange={setStatus} />

Validation states

Preview
Code
<Select id="plan" label="Plan" placeholder="Select a plan" required
  error="Please select a plan." options={[...]} />

<Select id="plan" label="Plan" disabled options={[...]} value="pro" />

With countries

Preview

Powered by countries-list + country-flag-icons.

Code
import { countries, getEmojiFlag } from 'countries-list';

const COUNTRY_OPTIONS = Object.entries(countries)
  .map(([code, data]) => ({ value: code, label: `${getEmojiFlag(code)} ${data.name}` }))
  .sort((a, b) => a.label.localeCompare(b.label));

<Select id="country" label="Country" placeholder="Select a country…"
  options={COUNTRY_OPTIONS} hint="Powered by countries-list." />

Searchable

Preview

Type to filter the list.

Code
<Select id="country" label="Country" placeholder="Select a country…" searchable
  options={COUNTRY_OPTIONS} value={val} onChange={(e) => setVal(e.target.value)}
  hint="Type to filter the list." />
Sourcemodules/ui/Select.tsx