Design System / 07.2
Inputs
Form controls for data entry and selection, with examples of validation, keyboard behavior, and mobile input constraints.
Underline field
A single-line input with the label hidden, set over a single hairline. The 16px text prevents iOS input zoom; focus keeps the baseline and adds a currentColor outline without shifting layout.
Live specimen
Rendered output
API reference
Inputs, types, and behavior
- Inputlabel
- Typestring
- BehaviorRequired; rendered sr-only for assistive tech.
- Input…rest
- Typeinput props
- BehaviorEverything else, including ref, spreads onto the <input>. className styles the root; inputClassName styles the control.
Ghost field
A boxed variant with a 15% ink hairline and the same 16px entry text. Keyboard focus draws inside the square edge without a shadow.
Live specimen
Rendered output
API reference
Inputs, types, and behavior
- Inputlabel
- Typestring
- BehaviorRequired; rendered sr-only.
- Input…rest
- Typeinput props
- BehaviorSpread onto the <input>, including ref. className styles the root; inputClassName styles the control.
Textareas
Multi-line versions of the fields above, in the same underline and ghost styles. Each has a 10svh minimum height and resizes vertically only, so the width never changes.
Live specimen
Rendered output
API reference
Inputs, types, and behavior
- Inputlabel
- Typestring
- BehaviorRequired; rendered sr-only, like the fields above.
- Input…rest
- Typetextarea props
- BehaviorSpread onto the <textarea>, including ref. Pass resize-none via inputClassName to pin the height.
Checkbox
A native checkbox under a 15px hairline square. Checking fills it with ink behind a currentColor paper check; a native mixed state uses a horizontal paper mark. Hover dims the row. The visible mark stays compact while the full label row meets the 44px target floor.
Live specimen
Rendered output
API reference
Inputs, types, and behavior
- Inputlabel
- Typestring
- BehaviorRequired; rendered visibly beside the box.
- Inputindeterminate
- Typeboolean = false
- BehaviorSets the native mixed state and draws a horizontal paper mark for partial group selection.
- Input…rest
- Typeinput props
- BehaviorSpread onto the native checkbox, including ref. className styles the label root; inputClassName styles the input.
Radio group
Native radio inputs under square hairline marks. The group is a real fieldset with a small uppercase legend and a shared input name, so arrow-key navigation comes from the platform.
Live specimen
Rendered output
API reference
Inputs, types, and behavior
- Inputlabel
- Typestring
- BehaviorRequired legend; hideLabel keeps it sr-only.
- Inputname
- Typestring?
- BehaviorShared input name — auto-generated when omitted.
- Inputlabel (Radio)
- Typestring
- BehaviorRequired; native props and ref reach the radio. Radio className styles its label root; inputClassName styles the input.
Select
A styled native select. The platform popup is unchanged, so accessibility comes from the browser. Squared and hairline-bordered, with 16px text, a 44px floor, and a currentColor chevron over the right padding.
Live specimen
Rendered output
API reference
Inputs, types, and behavior
- Inputlabel
- Typestring
- BehaviorRequired; rendered sr-only.
- Inputchildren
- TypeReactNode
- BehaviorNative <option> elements; the platform styles the list.
- InputclassName
- Typestring?
- BehaviorMerged onto the relative root; inputClassName styles the native select.
- Input…rest
- Typeselect props
- BehaviorSpread onto the <select>, including ref.
Switch
A two-state toggle with a square track instead of a pill. The track is the checkbox itself; a square knob slides across it, and the track fills with ink when on. Optional state labels swap in via CSS only.
Live specimen
Rendered output
API reference
Inputs, types, and behavior
- Inputlabel
- Typestring
- BehaviorRequired visible label; the entire 44px row toggles and self-dims on hover.
- InputstateLabels
- Type{ off, on }?
- BehaviorMono aria-hidden readout beside the label, swapped in CSS — no client state.
- Input…rest
- Typeinput props
- BehaviorSpread onto the native checkbox (role="switch"), including ref. className styles the label root; inputClassName styles the input.
Stepper
Minus and plus buttons flank a tabular-nums value in one shared hairline box. Typed edits stay in a draft and commit on blur or Enter; the buttons dim when they reach the min or max.
Live specimen
Rendered output
Uncontrolled
Controlled — 2 selected
Disabled
API reference
Inputs, types, and behavior
- Inputlabel
- Typestring
- BehaviorNames the role="group" and the sr-only input label; buttons announce "Decrease / Increase {label}".
- Inputvalue / onValueChange
- Typenumber / (v) => void
- BehaviorControlled pair; omit for uncontrolled use.
- InputdefaultValue
- Typenumber = 1
- BehaviorUncontrolled start value.
- Inputmin / max / step
- Typenumber
- Behaviormin defaults to 0 and positive step to 1; max is optional. Invalid rails normalize and commits clamp into range.
- Inputname / required / disabled / readOnly
- Typenative field props
- BehaviorApply to the number input; disabled and readOnly also stop both step buttons.
Slider
A native range input restyled to match the system: a 1px hairline track, a solid square ink thumb, and an offset focus ring. Keyboard behavior comes from the platform.
Live specimen
Rendered output
API reference
Inputs, types, and behavior
- Inputlabel
- Typestring
- BehaviorRequired; rendered sr-only.
- Input…rest
- Typeinput props
- BehaviorSpread onto the range input, including ref. className styles the root; inputClassName styles the range.
Search field
An underline field inside a role="search" form with an uppercase submit and a two-bar clear that restores focus. Wire onSearch, or omit it and let the form navigate as plain GET.
Live specimen
Rendered output
Submit to run a query
API reference
Inputs, types, and behavior
- Inputlabel
- Typestring = "Search"
- BehaviorNames the sr-only label, the placeholder, and the submit.
- InputonSearch
- Type(query) => void?
- BehaviorIntercepts submit with the query value (passed verbatim); omit for native GET submission.
- InputonValueChange
- Type(query) => void?
- BehaviorReceives typing and clear actions; pair with inputProps.value for controlled use.
- InputinputProps
- Typeinput props?
- BehaviorReaches the <input> (name defaults to "q"; value/defaultValue are supported); other props spread on the <form>.
- InputinputRef
- TypeRef<HTMLInputElement>?
- BehaviorFocuses or measures the inner search input; a form ref passes through the native form props.
Combobox
A text field with an ARIA listbox: substring filtering stays in the input, arrows move the active option, Enter commits, and Escape closes. The popup enters in 300ms and exits in 200ms with a reduced-motion fallback. This is an input primitive, not an overlay family duplicate.
Live specimen
Rendered output
No topic committed
API reference
Inputs, types, and behavior
- Inputlabel / options
- Typestring / readonly string[]
- BehaviorRequired accessible name and the full option set; matching is case-insensitive substring search.
- Inputvalue / onValueChange
- Typestring / (value) => void
- BehaviorControlled text pair. Omit value and seed defaultValue for uncontrolled use.
- InputonSelect
- Type(value) => void?
- BehaviorFires only when Enter or pointer input commits an option.
- InputinputProps
- Typeinput props?
- BehaviorNative name, required, disabled, readOnly, description, and event attributes for the text input.
- InputinputRef
- TypeRef<HTMLInputElement>?
- BehaviorDirect access to the inner combobox input.
- Inputplaceholder / emptyText
- Typestring?
- BehaviorInput hint and zero-results copy (default "No matches").
- InputclassName
- Typestring?
- BehaviorMerged last on the root positioning element.
Fieldset + field label
Groups form fields under a hairline top rule with a small dim mono legend, children stacked beneath. FieldLabel is the standalone visible label component for building custom rows.
Live specimen
Rendered output
API reference
Inputs, types, and behavior
- Inputlegend
- Typestring
- BehaviorRequired; the dim uppercase mono legend over the rule.
- Inputchildren
- TypeReactNode
- BehaviorStacked in a 14px items-start column so inline controls keep their width.
- InputFieldLabel
- Typelabel props
- BehaviorVisible uppercase label block — pair with any control via htmlFor/id.
Newsletter bar
A 16px email input and ink submit sharing one square hairline — a single bar, not two separate controls. Focus within draws an inset outline; the submit self-dims. Submit below to see the announced confirmation state.
Live specimen
Rendered output
API reference
Inputs, types, and behavior
- InputbuttonLabel
- Typestring?
- BehaviorSubmit label.
- Inputlabel
- Typestring?
- BehaviorAccessible name for the input.
- InputinputProps
- Typeinput props?
- BehaviorReaches the <input>; other props spread on the <form>.
Form status
Success and error render as paper-colored blocks with a small mono state label. Error keeps the same hairline but raises it from /15 to /60 ink instead of introducing a tint or changing geometry.
Live specimen
Rendered output
Received
Error
API reference
Inputs, types, and behavior
- Inputstate
- Type"success" | "error"
- BehaviorMaps to role="status" / role="alert".
- Inputlabel
- Typestring?
- BehaviorOverrides the small uppercase state label ("Received" / "Error").
- Inputchildren
- TypeReactNode
- BehaviorThe message body.
Date field
Three underline segments — DD / MM / YYYY — that auto-advance as they fill and step back on Backspace. The change callback only ever emits a complete, calendar-valid ISO date, or an empty string while partial. A complete impossible date is identified and explained in place.
Live specimen
Rendered output
Incomplete — emits an empty string
API reference
Inputs, types, and behavior
- Inputlabel
- Typestring
- BehaviorRequired visible group label (hideLabel keeps it sr-only); segments carry their own Day/Month/Year names.
- InputonValueChange
- Type(iso) => void?
- BehaviorEmits "YYYY-MM-DD" when complete and valid, "" otherwise — impossible dates like 31/02 are rejected.
- Inputvalue / defaultValue
- Typestring
- BehaviorISO strings. Semi-controlled: a controlled value is adopted only when complete and valid, so parent echo never wipes mid-typing.
- Inputname / required / disabled / readOnly
- Typefield props
- BehaviorRequired applies to all segments; name adds a disabled-aware hidden ISO form value.
- Inputaria-describedby
- Typestring?
- BehaviorDescription IDs are shared by the group and all three inputs.
Datepicker
An inline month grid built entirely from hairlines: mono tabular numerals, ink fill on the selected day, and a ring on today. Arrows move by day, PageUp/PageDown move by month, and Home/End jump to the start or end of the week. Min/max bounds clamp keyboard focus and disable unavailable dates.
Live specimen
Rendered output
Picked: 2026-07-17
API reference
Inputs, types, and behavior
- Inputvalue / defaultValue / onValueChange
- Typestring / string / (iso) => void
- BehaviorControlled or uncontrolled ISO selection. Invalid strings are ignored.
- InputweekStartsOn
- Type0 | 1 = 1
- Behavior1 = Monday (matches the DD/MM date format used here), 0 = Sunday.
- Inputlabel / min / max / disabled
- Typestring / ISO / ISO / boolean
- BehaviorThe calendar name defaults to Calendar. Invalid or contradictory bounds are ignored.
Renders inline by design — for an overlay, drop it into a Popover panel and wire onValueChange to close.
Color field
No color wheel: a mono hex field beside a live hairline-bordered swatch. Valid entries are normalized to lowercase #rrggbb; invalid ones keep the last color, set aria-invalid, and show a monochrome error. Presets keep an 18px mark inside a 44px target.
Live specimen
Rendered output
Last valid: #040404
API reference
Inputs, types, and behavior
- Inputlabel
- Typestring
- BehaviorRequired visible label; hideLabel keeps it sr-only.
- InputonValueChange
- Type(hex) => void?
- BehaviorReceives the normalized #rrggbb whenever the valid color changes — re-entering the same value does not re-fire; #rgb shorthand is expanded.
- Inputpresets
- Typestring[]?
- BehaviorSquare swatch row (aria-pressed marks the current one) writing through the same commit path.
- Inputvalue / defaultValue
- Typestring
- BehaviorHex strings; semi-controlled with the same echo-safe sync as DateField.
- InputinputProps
- Typeinput props?
- BehaviorNative name, required, disabled, readOnly, descriptions, classes, and input events.
- InputinputRef
- TypeRef<HTMLInputElement>?
- BehaviorDirect access to the inner text input.
Rating
No stars: a row of 13px squares, filled cumulatively with ink. Interactive mode is a native radio group — one tab stop, arrows to move — and readOnly renders a static labelled figure.
Live specimen
Rendered output
3 of 5
Disabled radio group
Read-only figure
API reference
Inputs, types, and behavior
- Inputvalue / defaultValue
- Typenumber?
- BehaviorControlled value or uncontrolled starting value, 1..max; 0 selects nothing.
- InputonValueChange
- Type(value) => void?
- BehaviorReceives interactive changes in controlled and uncontrolled use.
- Inputmax
- Typenumber = 5
- BehaviorCell count.
- InputreadOnly
- Typeboolean = false
- BehaviorStatic role="img" figure labelled "{label}: {value} of {max}".
- Inputlabel
- Typestring
- BehaviorRequired accessible name for the group or figure.
- Inputname
- Typestring?
- BehaviorShared radio name for the interactive group; auto-generated when omitted.
- Inputdisabled / required
- Typeboolean
- BehaviorNative radio-group states for interactive mode.
- InputclassName
- Typestring?
- BehaviorMerged onto the root element.
Text field
A boxed, labeled input that the Field kit deliberately leaves out — the Field kit stays underline/ghost-only, so TextField adds the box, error, and helper text that product and settings forms need. The hairline box gains a currentColor inset outline on focus; error uses ink, never red, sets aria-invalid, and owns the active description. Leading and trailing slots hold a prefix, unit, or small action at the /60 readability floor.
Live specimen
Rendered output
Lowercase letters, numbers, and hyphens.
This slug is already taken.
API reference
Inputs, types, and behavior
- Inputlabel
- Typestring
- BehaviorVisible mono uppercase label above the box.
- Inputerror
- Typestring?
- BehaviorError copy below the field — ink weight, sets aria-invalid, outlines the box, and replaces the hint as the active description.
- Inputhint
- TypeReactNode?
- BehaviorDimmed helper copy below the field.
- Inputleading / trailing
- TypeReactNode?
- BehaviorSlots at the input's start / end — a prefix, unit, or small action.
- InputlabelAction
- TypeReactNode?
- BehaviorSlot beside the label — e.g. an "Optional" tag or a link.
- InputclassName
- Typestring?
- BehaviorMerged onto the root. inputClassName styles the input; native props and ref pass through.
Secret field
A read-only display for an API key, token, or password. It’s masked by default behind a fixed-length run of characters, so a hidden secret never leaks its real length. An eye toggle reveals it, and a guarded copy button is available. The value is set in monospace and scrolls inside the box instead of widening it. Reveal state can be controlled or uncontrolled; the hint line can carry a one-time-secret warning. The display has read-only textbox semantics, and successful copy is announced politely.
Live specimen
Rendered output
Shown once — copy it now, it will not appear again.
API reference
Inputs, types, and behavior
- Inputvalue
- Typestring
- BehaviorThe secret to display — API key, token, password.
- Inputrevealed / defaultRevealed
- Typeboolean?
- BehaviorControlled reveal (pair with onRevealChange), or the initial state when uncontrolled. Default masked.
- InputonRevealChange
- Type(revealed: boolean) => void
- BehaviorFires whenever the reveal toggle flips.
- Inputlabel / hint
- TypeReactNode?
- BehaviorMono micro-label above the box and a dimmed helper line, e.g. a one-time-secret warning.
- Inputcopyable
- Typeboolean
- BehaviorShow the copy affordance. Default true.
- InputmaskChar / revealLabel / hideLabel
- Typestring
- BehaviorMask glyph (default "•", first code point only) and the toggle's aria-label / tooltip in each state ("Show" / "Hide").
- InputclassName / classNames
- Typestring? / { root, label, hint, field, value }?
- BehaviorclassName is an alias for classNames.root. field reaches the box (on --surface); value reaches the textbox, so a host can trade the horizontal scroll for wrapping. Restate leading alongside any font-size.
Password strength
A presentational segmented meter. The host computes the score; this component only renders segments squared bars and fills the proportion represented by the 0–4 score. Fills use companion tints in order (clay → ochre → slate → sage) and fall back to ink where the host hasn’t defined that color token, so strength stays readable by bar count alone. The demo maps input length to a 0–4 score locally, so the row updates as you type.
Live specimen
Rendered output
API reference
Inputs, types, and behavior
- Inputscore
- Type0 | 1 | 2 | 3 | 4
- BehaviorHost-computed strength (e.g. via zxcvbn). 0 = empty, 4 = strong.
- Inputsegments
- Typenumber
- BehaviorCount of squared bars in the row. Default 4; runtime values clamp to 1..20.
- InputshowLabel
- Typeboolean
- BehaviorShow the mono micro-label of the current level. Default true.
- Inputlabels
- Type[string, string, string, string, string]
- BehaviorLevel names indexed by score. Default "Too weak" … "Strong".
- Inputlabel
- TypeReactNode?
- BehaviorOverride the computed level label.
- InputclassName
- Typestring?
- BehaviorMerged onto the wrapper column.
Filter bar
A data toolbar that sits above a table. The top row pairs a SearchField and facet controls on the left with a right-aligned actions slot. Once filters apply, a second row appears below a hairline: squared chips with × removers plus a “Clear all” button when its callback is supplied. It’s slot-driven: the chips call the onRemove you pass, so no filter state lives inside.
Live specimen
Rendered output
API reference
Inputs, types, and behavior
- Inputsearch
- TypeReactNode?
- BehaviorA SearchField slot (top row, far left).
- Inputfilters
- TypeReactNode?
- BehaviorFacet controls — Select / Combobox / ButtonGroup slots (top row, left).
- Inputactions
- TypeReactNode?
- BehaviorRight-aligned slot, e.g. a "New" Button.
- Inputapplied
- Type{ id?, label, onRemove }[]?
- BehaviorApplied-filter chips; presence renders the second row. Supply id when chips can reorder.
- InputonClearAll
- Type() => void?
- BehaviorAdds and handles Clear all while chips exist.
- InputclassName
- Typestring?
- BehaviorMerged onto the root strip.