Playground
Overview
- Use
Select when users can scan the options without filtering. Use Combobox for search within the list.
When to use
- Use
Select for finite single-choice option sets where the user can comfortably scan the list. - Provide a visible label. Use
description for guidance and error for validation failures.
When not to use
- Do not use
Select when the list is long enough to require filtering; use Combobox. - Do not use
Select for multi-select.
Structural parts
field wrapper
root Provides the label, helper text, and validation shell.
field button
trigger Opens the listbox and reflects the current value.
options surface
listbox Anchored list of available options.
selectable row
option Single option row with label and optional description.
Public interface
Props| Name | Type | Default | Description |
|---|
value | string | — | Controlled selected value. |
items | Array<{ value: string; label: string; description?: string; disabled?: boolean }> | — | Available options. |
label | string | — | Visible field label. |
description | string | — | Supporting helper copy. |
error | string | — | Validation message. |
placeholder | string | — | Text shown before a selection is made. |
required | boolean | false | Marks the field as required. |
disabled | boolean | false | Disables the field. |
name | string | — | Native form field name. |
id | string | — | Optional field ID. |
size | 'sm' | 'md' | 'lg' | 'md' | Chooses the size recipe. |
onChange | (detail: { value: string | undefined }) => void | — | Runs when a value is selected. |
theme | ThemeContract | — | Sets the theme used to resolve component styles. |
Events| Name | Payload | Description |
|---|
change | { value: string | undefined } | Fires when the component commits a new value. |
Slots| Name | Description |
|---|
default | Select is data-driven and does not expose custom option slots. |
Variants, sizes, and states
Variants
default: Select uses one single-choice field shell and varies by size.
Sizes
sm: Compact selectmd: Default selectlg: Larger select
States
closed: Listbox hiddenopen: Listbox visibleselected: Value selectedinvalid: Validation state
Accessibility
Semantics
- Uses a button-trigger plus listbox relationship to expose the selectable options.
Keyboard
- Arrow keys move through options when the listbox is open and Enter commits the active option.
Screen readers
- Selected value, listbox state, and option movement remain explicit.
Checklist
- Verify that the control has an accessible name.
- Verify that keyboard focus is visible in every state and size.
- Identify disabled, selected, and error states with text or symbols as well as color.
Tokens and CSS variables
root
- --dk-field-stack-gap
- 0.45rem
- --dk-motion-duration
- 200ms
- --dk-select-offset
- 8px
label
- --dk-field-label-color
- #16181c
- --dk-field-label-size
- clamp(1.333rem, 1.2222rem + 0.494vw, 1.667rem)
- --dk-field-label-weight
- 600
trigger
- --dk-select-trigger-bg
- #f2f5fb
- --dk-select-trigger-fg
- #16181c
- --dk-select-trigger-border
- #95989d
- --dk-select-trigger-block-size
- 48px
- --dk-select-trigger-inline-padding
- clamp(1.333rem, 1.2222rem + 0.494vw, 1.667rem)
- --dk-select-trigger-radius
- clamp(0.75rem, 0.6875rem + 0.278vw, 0.938rem)
- --dk-select-trigger-font-size
- clamp(1.333rem, 1.2222rem + 0.494vw, 1.667rem)
icon
- --dk-select-icon-size
- 1rem
- --dk-select-icon-color
- #16181c
description
- --dk-field-description-color
- #16181c
- --dk-field-description-size
- clamp(0.75rem, 0.6875rem + 0.278vw, 0.938rem)
error
- --dk-field-error-color
- #cc272e
- --dk-field-error-size
- clamp(0.75rem, 0.6875rem + 0.278vw, 0.938rem)
surface
- --dk-select-surface-bg
- #f2f5fb
- --dk-select-surface-fg
- #16181c
- --dk-select-surface-border
- #95989d
- --dk-select-surface-radius
- clamp(1.333rem, 1.2222rem + 0.494vw, 1.667rem)
- --dk-select-surface-shadow
- 0 10px 15px rgba(0, 0, 0, 0.06), 0 4px 6px rgba(0, 0, 0, 0.04)
- --dk-select-surface-width
- 300px
- --dk-select-surface-padding
- clamp(0.75rem, 0.6875rem + 0.278vw, 0.938rem)
item
- --dk-select-item-bg
- transparent
- --dk-select-item-fg
- #16181c
- --dk-select-item-radius
- clamp(0.75rem, 0.6875rem + 0.278vw, 0.938rem)
- --dk-select-item-min-height
- 44px
- --dk-select-item-inline-padding
- clamp(1.333rem, 1.2222rem + 0.494vw, 1.667rem)
itemLabel
- --dk-select-item-label-size
- clamp(1.333rem, 1.2222rem + 0.494vw, 1.667rem)
- --dk-select-item-label-weight
- 550
itemDescription
- --dk-select-item-description-size
- clamp(0.75rem, 0.6875rem + 0.278vw, 0.938rem)
Implementation notes
Select supports one value and does not filter options.
Examples
Starter
Environment selector
A standard single-select field.
<Select label="Environment" description="Choose the deployment target." placeholder="Select an environment" items={items} />
Common patterns
Required selection
Set the error prop to explain a validation failure.
<Select label="Environment" error="Choose an environment." placeholder="Select an environment" items={items} />
Edge cases
Externally controlled listbox
Control the selected value when surrounding state owns the workflow.
<Select label="Environment" items={items} value={selectedEnvironment} onChange={(detail) => selectedEnvironment = detail.value} />
Mathematical fixtures
Calculated fixtures; browser evidence is not collected. Layout estimates use declared text behavior and maximum token values.
default (size=sm)
pass size=sm
- Evidence: mathematical
- Coverage: complete (4 / 4 declared kinds evaluated)
- Declared: contrast, target, optionRow, anchoredSurface
- Evaluated: contrast, target, optionRow, anchoredSurface
- Contrast: 98.5 Lc
- Target: 44 px
- Rows: 44 px
- Surface: 300 × 280 px
default (size=md)
pass size=md
- Evidence: mathematical
- Coverage: complete (4 / 4 declared kinds evaluated)
- Declared: contrast, target, optionRow, anchoredSurface
- Evaluated: contrast, target, optionRow, anchoredSurface
- Contrast: 98.5 Lc
- Target: 48 px
- Rows: 44 px
- Surface: 300 × 280 px
default (size=lg)
pass size=lg
- Evidence: mathematical
- Coverage: complete (4 / 4 declared kinds evaluated)
- Declared: contrast, target, optionRow, anchoredSurface
- Evaluated: contrast, target, optionRow, anchoredSurface
- Contrast: 98.5 Lc
- Target: 52 px
- Rows: 44 px
- Surface: 300 × 280 px
selected (size=sm)
pass size=sm
- Evidence: mathematical
- Coverage: complete (4 / 4 declared kinds evaluated)
- Declared: contrast, target, optionRow, anchoredSurface
- Evaluated: contrast, target, optionRow, anchoredSurface
- Contrast: 98.5 Lc
- Target: 44 px
- Rows: 44 px
- Surface: 300 × 280 px
selected (size=md)
pass size=md
- Evidence: mathematical
- Coverage: complete (4 / 4 declared kinds evaluated)
- Declared: contrast, target, optionRow, anchoredSurface
- Evaluated: contrast, target, optionRow, anchoredSurface
- Contrast: 98.5 Lc
- Target: 48 px
- Rows: 44 px
- Surface: 300 × 280 px
selected (size=lg)
pass size=lg
- Evidence: mathematical
- Coverage: complete (4 / 4 declared kinds evaluated)
- Declared: contrast, target, optionRow, anchoredSurface
- Evaluated: contrast, target, optionRow, anchoredSurface
- Contrast: 98.5 Lc
- Target: 52 px
- Rows: 44 px
- Surface: 300 × 280 px
invalid (size=sm)
pass size=sm
- Evidence: mathematical
- Coverage: complete (4 / 4 declared kinds evaluated)
- Declared: contrast, target, optionRow, anchoredSurface
- Evaluated: contrast, target, optionRow, anchoredSurface
- Contrast: 98.5 Lc
- Target: 44 px
- Rows: 44 px
- Surface: 300 × 280 px
invalid (size=md)
pass size=md
- Evidence: mathematical
- Coverage: complete (4 / 4 declared kinds evaluated)
- Declared: contrast, target, optionRow, anchoredSurface
- Evaluated: contrast, target, optionRow, anchoredSurface
- Contrast: 98.5 Lc
- Target: 48 px
- Rows: 44 px
- Surface: 300 × 280 px
invalid (size=lg)
pass size=lg
- Evidence: mathematical
- Coverage: complete (4 / 4 declared kinds evaluated)
- Declared: contrast, target, optionRow, anchoredSurface
- Evaluated: contrast, target, optionRow, anchoredSurface
- Contrast: 98.5 Lc
- Target: 52 px
- Rows: 44 px
- Surface: 300 × 280 px