Description
What it does
Dropdown presents a set of options in a collapsed control. The user clicks to reveal the list and selects one option, which collapses the list and displays the selected value.
Where it appears
Form fields with 7 or more options, filter controls, date/time pickers, and anywhere a radio group would occupy too much vertical space.
Why it exists
When options are too numerous to display simultaneously, hiding them in a dropdown reduces visual clutter without sacrificing completeness. The tradeoff is discoverability — users must open the list to see what's available.
Dropdown selects exactly one item. For multiple selections use Multi-Select. For binary on/off use Switch. For a small mutually exclusive set (under 7 options) where all options should be visible, use Radio Button.
Anatomy
| Part | Required? | Notes |
|---|---|---|
| Field label | Required | Describes what the user is selecting. Always visible — never use the selected value as a substitute for a label. |
| Selected value | Required | Shows the current selection. Displays placeholder text ("Choose an option") when nothing is selected yet. |
| Dropdown chevron | Required | Indicates the control expands. Direction reverses (↑) when open. |
| Options list | Required | The expanded list of options. Appears below (or above if space is limited) the trigger control. |
| Option item | Required | Each selectable choice. The current selection shows a check mark; hover and keyboard focus share one highlight, with a focus ring on the item. |
| Section heading | Optional | A quiet, semibold label that groups options. Not selectable. |
| Divider | Optional | A thin line between groups of options. |
Variants
Default
Closed control showing a placeholder or the current selection
The standard presentation for any single-select dropdown.
With hint
Adds supporting text below the control
When the field needs brief clarification that doesn't fit in the label.
Disabled
Control cannot be interacted with
When the value is locked by a preceding choice or permission level. Communicate why nearby.
Usage guidelines
When to use Dropdown vs other controls
| Situation | Use |
|---|---|
| 2–6 options, space available | Radio buttons — all options visible without interaction |
| 7+ options | Dropdown — list would be unwieldy as radio buttons |
| Space is constrained regardless of option count | Dropdown — even 3–4 options may suit a dropdown in dense UIs |
| Multiple selections needed | Multi-Select — not Dropdown |
| Binary on/off toggle | Switch — not a two-option Dropdown |
Do / Don't
Do
Use a clear placeholder like "Select a country" rather than blank. Users need to understand that an action is required.
Don't
Don't use a dropdown for 2 options that are simple opposites. "Yes / No" is better as a radio group or a checkbox.
Do
Pre-select a default value when one option is almost always correct. An empty dropdown forces unnecessary interaction.
Don't
Don't put critical actions inside a dropdown list. Options that delete or permanently change data should be in a clear, distinct UI — not buried in a collapsed list.
Layout & Spacing
| Element | Spec |
|---|---|
| Trigger height | 40px at medium (same as text input; five sizes from 24px to 56px) |
| Trigger padding | Horizontal 8 / 12 / 16 / 20 / 24px by size; the height is fixed. --orbit-form-control-size-*-padding-inline |
| Option item height | About 35px at medium: 16px text with 8px vertical padding |
| Option padding | Vertical 4 / 8 / 8 / 10 / 12px, horizontal 8 / 12 / 16 / 20 / 24px by size. --orbit-menu-size-*-padding-block, -padding-inline |
| List padding | 4px on every side. --orbit-menu-padding |
| Max list height | 280px (scrollable beyond) |
| Border radius (trigger) | 4px. --orbit-form-control-radius |
| Border radius (list) | 4px, items 2px. --orbit-menu-radius, --orbit-menu-item-radius |
| Chevron size | About 14×16px |
Component tokens
Dropdown menus and the Select option list share the --orbit-menu-* tokens, so the two popups always match. They are framework-neutral CSS variables, and every token aliases a Semantic token.
| Token | What it sets |
|---|---|
--orbit-menu-background, -border-color, -border-width, -radius, -padding |
The popup panel. |
| `--orbit-menu-shadow-{offset-x | offset-y |
| `--orbit-menu-item-{text | details |
--orbit-menu-item-state-hover |
One highlight for hover and keyboard focus (an overlay), plus the focus ring. |
--orbit-menu-item-disabled-text, -danger-text, -danger-icon |
Disabled and destructive items. |
--orbit-menu-item-selected-icon |
The tick on the selected option. |
| `--orbit-menu-heading-{color | font-weight}, --orbit-menu-divider-{color |
| `--orbit-menu-size-{xs | s |
| Element | Token |
|---|---|
| Trigger background | --orbit-form-control-outlined-background |
| Trigger border | --orbit-form-control-border |
| Trigger focus | --orbit-form-control-focus-ring-color (a focus ring, not a border change) |
| Selected value text | --orbit-form-control-text |
| Placeholder text | --orbit-form-control-placeholder |
| Options list background | --orbit-menu-background |
| Options list shadow | --orbit-menu-shadow-* |
| Option hover and keyboard highlight | --orbit-menu-item-state-hover (one overlay for both) |
| Tick on the selected option | --orbit-menu-item-selected-icon |
| Selected option | A check mark, not a different fill |
Engineering notes
- Custom listbox components require keyboard support for: Enter/Space to open, arrow keys to navigate options, Enter to select, Escape to close, Tab to close and move focus, and type-ahead filtering for long lists. This is significant implementation work — use native
<select>unless styling requirements make it impossible. - The native
<select>can be styled for most design requirements using CSS (appearance: nonefor custom chevron, custom background, border, padding). Falling back to a custom component is rarely necessary. - On mobile devices, native
<select>triggers the platform's native picker (iOS wheel picker, Android bottom sheet). This is a significant usability advantage — don't override it with a custom listbox for mobile users.
Keyboard interaction
| Key | Action |
|---|---|
| Tab | Moves focus to the select control. |
| Alt + Arrow Down / Space | Opens the option list. |
| Arrow Up / Arrow Down | Navigates between options. |
| Enter | Selects the focused option and closes the list. |
| Escape | Closes the list without changing selection. |
| Type a letter | Jumps to the first option starting with that character. |
Why it matters
Custom dropdown implementations consistently fail accessibility audits because they replicate only part of the keyboard contract. Type-ahead navigation, Escape dismissal, and correct announcement of the selected value on close are all routinely missed. The native <select> handles all of this correctly across every platform and screen reader — and it costs nothing to implement.
Required ARIA
| Pattern | Requirement |
|---|---|
| Native select | <label for> or wrapping <label>. Always visible — no placeholder-as-label. |
| Validation error | aria-invalid="true" on the select when invalid. aria-describedby pointing to the error message element. |
| Required field | required attribute on the select. Visually indicate with an asterisk in the label. |
| Custom listbox | Requires role="combobox", role="listbox", role="option", aria-expanded, aria-selected, and full keyboard implementation. |
Things to avoid
- Don't use the placeholder option ("Select a country") as the label. The label must always be visible above or beside the field.
- Don't build a custom dropdown to avoid native
<select>styling limitations without first trying CSS-only solutions (appearance: none, custom background, border, and chevron via background-image). - Don't use
onChangeto submit a form or trigger navigation immediately when a dropdown value changes. This breaks keyboard navigation and surprises users. Require an explicit submit action.