Custom single-value dropdown built on a button + listbox (no native <select>) with full keyboard navigation and tone/size/surface theming.
WAI-ARIA combobox + listbox semantics — aria-expanded, aria-haspopup, aria-selected wired to the trigger and options.
Full keyboard support: ArrowUp/Down, Home/End, Enter/Space to select, Escape to close, Tab to dismiss.
Controlled — value + onChange (React), v-model (Vue), [(value)] or forms (Angular) — or uncontrolled with defaultValue; the value is the selected option value, as a string.
Form-friendly — hidden mirror input lets the value participate in native <form> submissions via name.
Tone, size, and surface (pixel/linear) variants share the same primitives as the rest of the input family.
Status
stable
Category
forms
Since
v1.0.0
API
import { PixelSelect } from '@pxlkit/ui-kit';
Prop
Type
Default
Description
label
string
—
Floating label rendered above the trigger.
options* (required)
Option[]
—
Items rendered in the listbox.
value
string
—
Controlled value. Make sure to update via onChange.
defaultValue
string
—
Uncontrolled initial value.
onChange
(value: string) => void
—
Fires when the user picks an option.
placeholder
string
'Select...'
Placeholder shown when no value is selected.
hint
string
—
Helper text shown below the field. Hidden when error is set.
error
string
—
Error message shown below the field; flips visual state to invalid.
Visual tone for focus ring + selected option. Default: 'neutral'.
size
'sm' | 'md' | 'lg'
'md'
Trigger height token. Default: 'md'.
surface
'pixel' | 'linear'
—
Surface variant. Inherits from PxlKitSurfaceProvider when omitted.
name
string
—
Sets name on the hidden serialization input so the value participates in native <form> submissions.
required
boolean
—
Marks the field as required for native form validation.
id
string
—
DOM id forwarded to the trigger.
aria-describedby
string
—
aria-describedby of the trigger; the hint / error is added while it shows.
ref points to <button>.
Accessibility
WCAG target: 2.1 AA
combobox
listbox
Trigger is a <button role="combobox"> paired with a role="listbox" popup containing role="option" children. Provide an accessible name via label; the hint/error it shows is linked through aria-describedby, after any ids you pass, and error automatically sets aria-invalid.
Keyboard
Key
Action
When
Enter
Opens the listbox, or selects the highlighted option when open.
—
Space
Opens the listbox, or selects the highlighted option when open.
—
ArrowDown
Opens the listbox or moves highlight to the next option.
—
ArrowUp
Moves highlight to the previous option.
—
Home
Highlights the first option (opening the listbox if needed).
—
End
Highlights the last option (opening the listbox if needed).
—
Escape
Closes the listbox without changing the selection.
—
Tab
Closes the listbox and moves focus to the next focusable element.