Select
FreeA native dropdown selector for choosing one option from a predefined list. Uses the browser-native <select> element for maximum accessibility and mobile-friendliness. Supports placeholder, disabled, and error states.
8 variants
Variants
| Variant | Description | When to use |
|---|---|---|
| Default | Standard select with a chevron indicator and placeholder option. | Use for choosing one option from a list of 5 or more items. |
| With Placeholder | ||
| Grouped |
Usage Guidelines
Do
Use a placeholder option like "Select an option..." that is disabled and selected by default.
Don't
Use a custom dropdown for fewer than 5 options — use Radio buttons instead.
Do
Always pair with a visible <label> element.
Don't
Hide the label — placeholder text inside the select is not a label.
Do
Order options logically — alphabetically, by frequency, or by importance.
Don't
Rely on the default browser styling without any design-system treatment.
Do
Use native <select> for mobile-friendly option picking.
Don't
Code
HTML
<div class="lex-field">
<label class="lex-label" for="country-select">Country</label>
<div class="lex-select-wrapper">
<select id="country-select" class="lex-select" aria-required="true">
<option value="" disabled selected>Select a country...</option>
<option value="us">United States</option>
<option value="gb">United Kingdom</option>
<option value="de">Germany</option>
<option value="fr">France</option>
</select>
<svg class="lex-select__chevron" width="16" height="16" viewBox="0 0 24 24"
fill="none" stroke="currentColor" stroke-width="2">
<polyline points="6 9 12 15 18 9" />
</svg>
</div>
</div>CSS Custom Properties
.lex-select-wrapper {
position: relative;
display: inline-flex;
width: 100%;
}
.lex-select {
width: 100%;
height: var(--lex-input-height, 40px);
padding: 0 var(--lex-input-padding, 12px);
padding-right: 36px;
background: var(--lex-input-bg);
border: 1px solid var(--lex-input-border);
border-radius: var(--lex-input-radius, var(--lex-radius-md));
color: var(--lex-input-text);
font-size: var(--lex-font-size-sm);
appearance: none;
cursor: pointer;
transition: border-color 150ms ease, box-shadow 150ms ease;
}
.lex-select:focus {
outline: none;
border-color: var(--lex-input-border-focus);
box-shadow: 0 0 0 2px var(--lex-input-ring);
}
.lex-select__chevron {
position: absolute;
right: 12px;
top: 50%;
transform: translateY(-50%);
pointer-events: none;
color: var(--lex-input-placeholder);
}
.lex-select:disabled {
background: var(--lex-input-bg-disabled);
color: var(--lex-input-text-disabled);
cursor: not-allowed;
}React
// Using Lexicon CSS classes with React
export function CountrySelect() {
return (
<Select label="Country" placeholder="Select a country..." required>
<Option value="us">United States</Option>
<Option value="gb">United Kingdom</Option>
<Option value="de">Germany</Option>
<Option value="fr">France</Option>
</Select>
);
}Design Tokens
| Token | Value (dark) | Value (light) | CSS property |
|---|---|---|---|
| --lex-input-bg | — | — | bg |
| --lex-input-border | — | — | border |
| --lex-input-radius | — | — | radius |
| --lex-select-arrow-color | — | — | color |
| --lex-menu-bg | — | — | bg |
Accessibility
- Native <select> provides built-in keyboard navigation and screen reader support.
- Always associate with a visible <label> via htmlFor/id.
- Error state uses aria-invalid="true" and aria-describedby for the error message.
- Disabled options should use the disabled attribute, not aria-disabled.