Selector
A dropdown that lets users choose one or more options from a predefined list. Available in three variants: simple, single (with radio indicators), and multiple (with checkbox indicators).
Use fd-selector when users need to pick from a set of predefined options and the list is too long for inline radio buttons or checkboxes (roughly 6+ options), or when screen space is constrained. The component provides a trigger control that opens a listbox popup with full keyboard and screen reader support.
When to use
- The option list is too long for visible radio buttons or checkboxes — Selectors save space by hiding options behind a trigger.
- Users need to select from a predefined, stable set of options — Account types, report categories, filing classifications.
- Screen space is constrained — Selectors use a single row plus a popup, compared to one row per option for radios or checkboxes.
- The workflow still owns submit behavior — Use
fd-selectorfor the choice itself, but keep native<form>semantics and a submit control such asfd-button type="submit"around it when the selection is part of a submitted workflow.
When not to use
- 5 or fewer options, single select — Use
fd-radio-groupinstead so all options are visible without interaction. Visible options are always easier to understand than options hidden behind a trigger. - 5 or fewer options, multi-select — Use
fd-checkbox-groupinstead. - Users need to type to search or filter — This component has no text input. Use a combobox pattern for search-as-you-type.
- Navigation menus or action lists — Use
fd-menu/fd-menu-item. Selectors are for form values; menus are for commands. - Multi-select in high-stakes government workflows — Multi-select dropdowns hide selected state behind a trigger, creating comprehension risk. Prefer
fd-checkbox-groupfor consequential multi-selection scenarios (filing types, regulatory classifications) even when the option count exceeds 5. - Highly consequential single-choice selections — If a selection triggers an irreversible action, prefer radio buttons with a separate submit button for explicit confirmation.
fd-fieldcomposition — Do not wrapfd-selectorinfd-field. Usefd-selectordirectly or wrap it infd-form-fieldwhen you want the shared long-term field-shell contract.
Examples
Properties
| Name | Type | Default | Description |
|---|---|---|---|
variant | "simple" | "single" | "multiple" | simple | Visual and interaction variant. multiple enables multi-selection and checkbox indicators. |
label | string | `` | Built-in field label text |
name | string | `` | Submitted form field name |
value | string | `` | Current selected value. In multiple mode, this mirrors the first selected value in DOM order. |
values | string[] | [] | Property-only API for reading or setting all selected values in multiple mode |
disabled | boolean | false | Prevents opening and selection changes |
required | boolean | false | Requires a selection. In multiple mode, requires at least one selected option. |
open | boolean | false | Current popup state |
placeholder | string | Select… | Trigger text shown when nothing is selected |
Slots
| Name | Description |
|---|---|
description | Group-level help text announced from the trigger |
| (default) | One or more fd-option children |
error | Group-level validation message shown and announced while invalid |
Events
| Name | Detail | Description |
|---|---|---|
input | Native Event | Fired when the current selection changes |
change | Native Event | Fired after the current selection changes |
fd-selector-change | { value: string, values: string[] } | Fired for both single- and multi-select changes |
fd-selector-open-change | { open: boolean } | Fired whenever the popup opens or closes |
Compatibility note:
fd-selectorstill fires deprecatedfd-selector-openandfd-selector-closeduring the compatibility window.- New consumer code should listen to
fd-selector-open-change.
CSS custom properties
| Name | Default | Description |
|---|---|---|
--fd-selector-required-color | #d80e3a | Required marker color |
--fd-selector-trigger-height | 44px | Minimum trigger height |
--fd-selector-trigger-border | var(--fdic-color-border-input, #bdbdbf) | Trigger border color at rest |
--fd-selector-border-radius | var(--fdic-corner-radius-sm, 3px) | Shared corner radius for trigger and popup |
--fd-selector-trigger-bg | var(--fdic-color-bg-base, #ffffff) | Trigger background color |
--fd-selector-trigger-border-focus | var(--fdic-color-border-input-focus, #38b6ff) | Focus ring color |
--fd-selector-error-border | #d80e3a | Trigger border color while visible invalid state is active |
--fd-selector-trigger-placeholder | var(--fdic-color-text-secondary, #595961) | Placeholder text color |
--fd-selector-dropdown-max-height | 280px | Maximum popup height before internal scrolling |
--fd-selector-dropdown-bg | var(--fdic-color-bg-base, #ffffff) | Popup background color |
--fd-selector-dropdown-border | var(--fdic-color-border-input, #bdbdbf) | Popup border color |
--fd-selector-dropdown-shadow | 0px 1px 2px rgba(0, 0, 0, 0.1), 0px 2px 12px rgba(0, 0, 0, 0.1) | Popup shadow |
--fd-selector-error-color | #d80e3a | Error text color |
Shadow parts
| Name | Description |
|---|---|
base | Outer selector wrapper |
label | Built-in label element |
label-text | Label text wrapper |
required-marker | Required asterisk |
description | Optional description wrapper |
trigger | Trigger surface. In simple and single variants, this is the native trigger button; in multiple mode, this is the trigger shell that contains removable chips and a separate trigger button. |
value-display | Selected value or placeholder text wrapper |
selected-chip | Embedded fd-chip selected option shown inside the trigger in multiple mode |
trigger-button | Separate native popup trigger button used in multiple mode |
chevron | Trigger chevron wrapper |
listbox | Popup listbox container |
error | Error message wrapper |
Best practices
Use clear, descriptive option labels
Each option should be unambiguous. Lead with human-readable text when options include codes: "Checking (001)" not "001 — Checking".
Use jargon or abbreviations without explanation
Option labels with unexplained abbreviations slow users down and increase error rates, especially in public-service forms.
Pair selectors with explicit submit buttons
Never auto-submit a form when a selector value changes. Users need a chance to review their choice.
Default to multi-select for government forms
Multi-select dropdowns are harder to scan than visible checkbox groups. Reserve them for low-stakes contexts like filters or preferences.
Content guidelines
- Placeholder text: Use "Select…" for simple/single, or "Select one or more…" for multiple. Never leave the trigger blank.
- Option descriptions: Use the
descriptionattribute onfd-optionwhen options benefit from additional context. Keep descriptions concise (one line). - Option ordering: Order options logically (most common first), alphabetically, or by category. Avoid arbitrary ordering.
- Required fields: The required marker (red asterisk) appears in the label. Validation messages are clear and specific: "Please select an option." or "Please select at least one option."
Accessibility
fd-selector uses the button + listbox ARIA pattern — the most conservative, widely-supported model for custom select components.
- Trigger: A native
<button>witharia-haspopup="listbox"andaria-expanded. - Listbox:
role="listbox"witharia-activedescendantfor focus tracking.aria-multiselectable="true"only for the multiple variant. - Options:
role="option"witharia-selected. All options have an explicitaria-selectedvalue in multi-select mode. - Keyboard: Enter/Space opens; Arrow keys navigate; Enter/Space selects (single) or toggles (multi); Escape closes; Tab closes and advances; Home/End jump to first/last; type-ahead (500ms) matches option text.
- Focus: DOM focus moves to the listbox when open. Focus returns to the trigger on close. Focus is not trapped.
- Validation contract:
checkValidity()updates and returns validity without revealing invalid state.reportValidity()reveals invalid state only when the selector is invalid; if the selector is valid, it has no visible effect. - Visibility boundaries: invalid state becomes visible on form submit attempts, explicit
reportValidity(), and popup close or focus-out after user interaction. - Invalid ownership: the host carries
data-user-invalid; the trigger control carriesaria-invalid="true"only while that visible invalid state is active. - Clearing behavior:
aria-invalidis present iffdata-user-invalidis present, and both clear in the same update cycle when the selector becomes valid or when the form reset path runs. - Error content: provide authored error text in the
errorslot whenever the selector can block submission. Missing error copy is incomplete usage even though invalid styling still appears. - Selection indicators: Radio dots (single) and checkboxes (multiple) provide a shape-based indicator alongside background color, so selection is never conveyed by color alone.
- Live region: In multi-select mode, an
aria-live="polite"region announces the selection count. - Forced colors: High Contrast mode overrides use system colors for borders and selection.
- Reduced motion: Chevron rotation and dropdown animation are suppressed under
prefers-reduced-motion.
fd-option contract
fd-option is a supporting embedded primitive. It stays documented here because its meaning depends on the fd-selector parent.
Purpose and relationship to parent
- Use
fd-optiononly as a child offd-selector. - It provides the authored option label, optional description, and disabled state that
fd-selectorturns into listbox options.
Supported authored surface
| Name | Type | Default | Notes |
|---|---|---|---|
value | string | "" | Submitted value for the option |
description | string | "" | Optional secondary line for added context |
disabled | boolean | false | Keeps the option visible but unavailable |
| default slot | text | — | Primary visible option label |
Authoring constraints
fd-optionmust be authored insidefd-selector; standalone use is unsupported.- Provide a stable
valuefor every option. Do not rely on label text as the submitted value. - Keep descriptions concise and supplemental. They should clarify, not replace, the primary label.
- Avoid mixing long descriptive copy with high-stakes multi-select workflows where visible checkbox groups would be clearer.
Accessibility contract
fd-optionitself is not the focus owner.fd-selectormanages listbox semantics, active descendant, selection state, and keyboard interaction.- The parent projects
fd-optioncontent intorole="option"semantics and exposesaria-selectedstate. - Disabled options remain visible for discoverability but cannot be selected.
Usage example
<fd-selector label="Account type" variant="single">
<fd-option value="checking">Checking</fd-option>
<fd-option value="savings" description="Daily-use savings account">
Savings
</fd-option>
<fd-option value="cd" disabled>Certificate of Deposit</fd-option>
</fd-selector>Known limitations
- No search or filtering — This is a static-list selector, not a combobox. A separate
fd-comboboxshould be built for type-ahead use cases. - No option groups — Grouped options (like
<optgroup>) are not supported in v1. - No chip/tag display — Multi-select shows comma-separated text with ellipsis truncation. Chip/tag display is deferred.
- No async option loading — All options must be present in the DOM at render time.
Related components
- Form Field — wrapper-based shell for shared label, description, and error authorship across control families