Select
A single-choice form control whose trigger opens a mobile option sheet and mirrors the committed value into form submission.
Implementation previewEvery example. In one place.
Explore every named example, including states, compositions, and theme variants.
Example source
packages/design-system/src/components/forms/Select/Select.stories.tsxExport PlaygroundImplementation preview Local Storybook build 0.2.0-preview.1. Source specification status does not approve this runtime.
Stories + source JSON ↗Local specification source status: preview. Implementation preview pending sign-off.
A single-choice form control whose trigger opens a mobile option sheet and mirrors the committed value into form submission.
Implementation API 1 entry point · source-derived preview
Read the actual callable API and preserve its composition constraints. Each union branch is a complete alternative; props marked forbidden cannot be supplied.
import { Select } from '@cloakedinc/design-system';SelectSelectProps
packages/design-system/src/components/forms/Select/Select.tsx:63
| Prop | Type | Presence | Notes |
|---|---|---|---|
value | string | Required | Value of the selected option; a value matching no option shows the placeholder. |
options | SelectOption[] | Required | Choices in the order the sheet lists them. An empty array opens an empty sheet. |
onChange | ((value: string) => void) | undefined | Optional | Called with the chosen value, just before the sheet closes. |
placeholder | string | undefined | Optional | Trigger text when nothing is selected. Defaults to `Select an option`.Source default: 'Select an option' |
sheetTitle | string | undefined | Optional | Title shown in the option sheet. Falls back to `ariaLabel` or placeholder. |
surface | SelectSurface | undefined | Optional | Container background treatment.Source default: 'default' |
disabled | boolean | undefined | Optional | Blocks the trigger from opening the sheet. |
required | boolean | undefined | Optional | Announces the field as required to assistive tech. The hidden input is barred from constraint validation, so this cannot block a submit. |
ariaLabel | string | undefined | Optional | Accessible name when no visible label is associated with the field. |
haptic | HapticFeedback | undefined | Optional | Haptic feedback for value changes. Defaults to `true` (`selection`).Source default: true |
name | string | undefined | Optional | Field name for the hidden input that carries `value` into a form submit. |
onFocus | (() => void) | undefined | Optional | Called when the trigger button takes focus; rows inside the sheet do not report focus. |
onBlur | (() => void) | undefined | Optional | Called when the trigger button loses focus. |
className | string | undefined | Optional | |
style | React.CSSProperties | undefined | Optional | |
testId | string | undefined | Optional | Test id for the trigger; the sheet and its option rows derive from it. |
id | string | undefined | Optional | DOM id the control renders, which the Field's label points at. |
invalid | boolean | undefined | Optional | Paints the invalid treatment and announces the control as invalid. A Field supplies this from its own `error`; set it directly only for a control with no Field around it. |
ariaDescribedBy | string | undefined | Optional | Ids of the helper or error copy describing the control, supplied by a parent Field. |
ariaLabelledBy | string | undefined | Optional | Id of the visible label naming the control, supplied by a parent Field. |
Only explicit destructured parameter initializers are extracted. Other runtime defaults remain in implementation source.
Overview
A form control for picking one value from a short, known list. The trigger opens a
native-feeling bottom sheet (BottomSheet + Menu) and submits a hidden <input>.
When to use
Reach for Select when the choice is a single required value drawn from a short, fixed set —
a preferred contact method, a state, a category. It is the mobile equivalent of a <select>:
the options stay hidden until tapped.
- List long enough that you'd want to type to narrow it? Use
Autocomplete— it filters as you type. - Want every option visible inline without opening a sheet? Use
RadioGroup(orSegmentedControlfor 2–4). - Just need a trigger + floating panel with no form-value semantics? Use
Dropdownwith aMenu.
In-app it backs the data-removal profile fields (FormField.tsx) and the exposures broker filter
(BrokerListSection.tsx). Pair it with Field for a label and validation copy — the Field's
error turns this trigger red on its own; invalid is the escape hatch outside a Field.
Component specification
$schema
../../../specs/component-spec.schema.jsonParts
- Id
- root
- Label
- Root
- Description
- Stacks the hidden form value and the visible trigger.
- Id
- form-value
- Label
- Form value
- Description
- Hidden native input carrying name, value, disabled, and required state.
- Id
- trigger
- Label
- Trigger
- Description
- Displays the placeholder or selected label and opens the option dialog.
- Id
- trigger-label
- Label
- Trigger label
- Description
- Truncates the current option label without displacing the affordance.
- Id
- chevron
- Label
- Chevron
- Description
- Trailing visual indicating that the trigger reveals choices.
- Id
- sheet
- Label
- Option sheet
- Description
- Modal surface containing the single-select Menu.
- Id
- option
- Label
- Option
- Description
- Menu row with optional leading content, disabled state, and selected check.
Allowed Design Choices
- Variants
- Sheet
- Label
- Sheet
- Description
- The form trigger presents one short, fixed choice list in a modal sheet.
- Sizes
- Surfaces
- Default
- Label
- Default
- Description
- Uses the semantic input container.
- Raised
- Label
- Raised
- Description
- Uses the raised surface when placed directly on the page canvas.
Variants
- Id
- sheet
- Label
- Sheet
- Description
- Single-choice form trigger backed by a modal Menu.
- Platforms
- ios
- android
- web
Sizes
None specifiedMeasurements
- Id
- trigger-height
- Label
- Trigger height
- Kind
- exact
- Token
- --cds-size-56
- Value
- 56
- Unit
- px
- Applies To
- trigger
- Id
- trigger-leading-padding
- Label
- Trigger leading padding
- Kind
- exact
- Token
- --cds-space-20
- Value
- 20
- Unit
- px
- Applies To
- trigger
- trigger-label
- Id
- trigger-trailing-padding
- Label
- Trigger trailing padding
- Kind
- exact
- Token
- --cds-space-20
- Value
- 20
- Unit
- px
- Applies To
- trigger
- chevron
Layout
- Alignment
- Trigger label remains leading and flexible while the chevron remains trailing.
- Flow
- Hidden form value and visible trigger share one root; the trigger presents a modal list of options.
- Notes
- Use RadioGroup when all choices should remain visible.
- Use Autocomplete when a long or dynamic list needs type-to-filter.
Typography And Color
- Typography
- Label
- Trigger label
- Description
- Use the body ramp for placeholder and selected option text.
- Token
- --cds-type-body-size
- Colors
- Label
- Default surface
- Description
- Use the semantic input container.
- Token
- --cds-input-container
- Label
- Raised surface
- Description
- Use the raised semantic surface.
- Token
- --cds-bg-surface
- Label
- Selected label
- Description
- Use primary text emphasis for the committed value.
- Token
- --cds-text-primary
- Label
- Placeholder and chevron
- Description
- Use secondary text emphasis before selection and for the affordance.
- Token
- --cds-text-secondary
- Label
- Validation
- Description
- Use the solid danger role for invalid border and copy.
- Token
- --cds-status-danger-solid
States
- Id
- empty
- Label
- Empty
- Description
- Shows placeholder copy and an empty form value.
- Id
- selected
- Label
- Selected
- Description
- Shows the current option label and selected option in the sheet.
- Id
- open
- Label
- Open
- Description
- Exposes expanded state and presents the labelled option dialog.
- Id
- invalid
- Label
- Invalid
- Description
- Shows the danger border and invalid semantics. The corrective message belongs to the enclosing Field.
- Id
- disabled
- Label
- Disabled
- Description
- Disables form submission, opening, focus interaction, and option changes.
Behavior
- Label
- Open
- Description
- Present the option sheet only from an enabled trigger.
- Label
- Select
- Description
- Emit the next option value, close the sheet, and mirror the controlled value into the hidden input.
- Label
- Form submission
- Description
- Submit the controlled string under the optional name; required surfaces as aria-required on the trigger only, since the hidden input skips native constraint validation.
Accessibility
- Label
- Trigger name and state
- Description
- Associate a visible Field label or accessible label and expose dialog popup, expanded, required, invalid, and described-by states.
- Label
- Option sheet
- Description
- Name the modal and its single-select listbox from the field or explicit sheet title.
- Label
- Options
- Description
- Expose selected and disabled state for every option.
Content Adaptation
- Label
- Long selected labels
- Description
- Truncate the one-line trigger label while allowing full labels to wrap in option rows.
- Label
- Placeholder
- Description
- Name the choice being requested instead of repeating a generic Select instruction.
Motion Haptics
- Motion
- Label
- Sheet presentation
- Description
- Delegate opening and dismissal motion to Modal; selection closes the sheet without animating the trigger geometry.
- Haptics
- Label
- Selection feedback
- Description
- Request the selection haptic after an enabled option is chosen.
Platform Differences
- Platforms
- web
- Description
- Web mirrors the selected value into a hidden input and uses an ARIA dialog/listbox composition rather than a native HTML select.
- Rationale
- The mobile bottom-sheet interaction is the cross-platform product pattern, while the hidden input preserves web form submission.