Select
Dropdown select fields for choosing from a predefined list of options. Uses the same .input class as all form fields — identical styling, focus ring, and validation states.
Overview
Select uses the native <select> element with the .input class applied. This ensures visual consistency with text inputs and textareas. Always include a blank default option with a descriptive placeholder like "Select role..." when no default is pre-selected.
Variants
Filter by regional assignment.
Please select a status.
Filter Bar Select
In filter bars, selects are used without labels, inside a flex row. They use the same .input class with flex:1; min-width:160px.
AI Implementation Notes
For AI coding assistants: Select uses the native HTML
<select> element with the .input class — no custom dropdown component needed. Always include an empty first option for unselected state: <option value="">Select...</option>. Error state: add .input-error to the select AND render .form-error-msg below. In filter bars, omit the label and use flex:1; min-width:160px.When to Use
Use Select when
- Choosing one option from 4–15 predefined choices
- Filter bars (role, status, region)
- Form fields with enumerated values
Don't use Select when
- Only 2–3 options — use radio buttons or a button group
- User can type a custom value — use a combobox
- More than 15 options — use searchable select
Properties
| Property | Type | Required | Default | Description |
|---|---|---|---|---|
| options | array | required | — | Array of option objects or strings: {value, label}. Always include a blank first option as placeholder: {value:'', label:'Select...'}. |
| value | string | optional | '' | Currently selected value. |
| error | string | optional | undefined | Error message. Adds .input-error to select and .form-error-msg below. |
| disabled | boolean | optional | false | Disabled state. Same visual treatment as input. |
Design Decisions
Why use native select instead of a custom dropdown component?
Native select elements have built-in accessibility (keyboard navigation, screen reader support), work on all devices including touch, and require zero JavaScript. Custom dropdowns require significant effort to match this accessibility baseline. For simple list selection, native select is the correct choice. Complex cases (multi-select, searchable, grouped) would warrant a custom component.
Changelog
v1.0.0July 2026Added
- Native select with .input class — consistent with input/textarea styling
- Filter bar usage pattern documented
Default
border:#E2E8F0, placeholder shown
Focus
border:#3B5BDB + 3px ring
Required
Error
border:#F05252 + error msg
Disabled
bg:#F8FAFC, cursor:not-allowed
Accessibility
| Requirement | Implementation |
|---|---|
| label | Always link label via for/id. Label class: .form-label. Never use placeholder as label substitute. |
| aria-required | Add aria-required="true" for required fields. |
| aria-invalid | Add aria-invalid="true" when in error state. |
| Native select | Use native <select> — has built-in keyboard navigation, screen reader support, touch support. |
Composition
Allowed
Inside .form-group with .form-label
Filter bar without label (flex:1 min-width:160px)
Modal form fields
Forbidden
Without a label or aria-label
More than 15 options without grouping
As navigation trigger — use Dropdown instead
Best Practices
Do
Always include a blank first option as placeholder:
<option value="">Select...</option>Users need a clear unselected state — especially for required fields.
Don't
Pre-select the first real option by default when no selection is valid yet.
Pre-selecting hides the fact that no choice has been made, causing silent form submission errors.
Related Components
Anatomy
1
Label
label.form-label. UPPERCASE 12px fw-700 letter-spacing:.5px. Always linked via for/id. Never omitted.
2
Select Element
Native <select class="input">. Same styling as text input. cursor:pointer, appearance:auto (native dropdown arrow retained).
3
Options
First option always value="" as placeholder. Remaining options as <option value="key">Label</option>.
4
Validation Message
div.form-error-msg when invalid. Same pattern as input error states.
Content Rules
Good placeholder
Select role...
Clear, lowercase, with ellipsis indicating selection needed
Bad placeholder
--Choose--
Dashes are visual noise. Use natural language.
States
Default
border:#E2E8F0, placeholder visible
Focus
border:#3B5BDB + 3px ring
Error
border:#F05252 + error msg below
Disabled
bg:#F8FAFC, cursor:not-allowed
Behavior
| Trigger | Behavior |
|---|---|
| Click / Focus | Opens native browser dropdown. border-color:#3B5BDB + box-shadow focus ring applied. Native dropdown renders OS-specific UI. |
| Option select | Updates value, fires onChange event, closes dropdown. If value="" (placeholder), field is considered empty/unselected. |
| Blur | Focus ring removed. Validation triggers if field has been touched. Error state applied if validation fails. |
| Keyboard | Arrow keys navigate options. Enter selects. Escape closes. Tab moves to next field. All native browser behavior. |
| Disabled | Cannot be opened or changed. cursor:not-allowed. bg:#F8FAFC, opacity:.75. |
| Filter bar | In filter bar context, fires onChange immediately which re-filters the data — no submit button required. |