⚠️ Design system CSS not found. Check the path in cms/docs.config.js → designSystemPath, then re-run npm run docgen.

Form

Inputs, controls, and data collection patterns

Design System / Form
Download .md file
Open .md in new tab

Form elements are styled globally using semantic tokens. All text inputs, textareas, selects, checkboxes, and radios share consistent sizing, focus states, and disabled styling.


Labels

Labels are styled as block elements with medium weight:

<label for="name">Full name</label>
<input type="text" id="name" placeholder="Enter your name">

Properties: display: block, font-size: var(--font-s), font-weight: var(--font-weight-medium), bottom margin for spacing from the input.


Text Inputs

All standard text input types are styled globally:

<input type="text" placeholder="Text">
<input type="email" placeholder="Email">
<input type="password" placeholder="Password">
<input type="number" placeholder="Number">
<input type="search" placeholder="Search">
<input type="url" placeholder="URL">
<input type="tel" placeholder="Phone">

Properties: full width, font-size: var(--font-m) (matches body text), padding: var(--space-m) var(--space-l), border from , smooth focus transition.


Focus State

All inputs share a consistent focus style:

  • Border color changes to
  • A subtle box-shadow ring appears (2px, 75% transparent)
  • No outline (replaced by box-shadow for consistency)

This is accessibility-safe and keyboard-visible.


Textarea

Textareas have a minimum height and allow vertical resizing:

<label for="message">Message</label>
<textarea id="message" placeholder="Enter your message..."></textarea>

Properties: min-height: 120px, resize: vertical.


Select

Selects use a custom dropdown arrow via an inline SVG background:

<label for="country">Country</label>
<select id="country">
  <option value="" disabled selected>Choose a country</option>
  <option value="nz">New Zealand</option>
  <option value="au">Australia</option>
</select>

Properties: appearance: none, custom caret, right padding for arrow space.


Colour Input

The native colour picker is styled to match other form inputs. Browser chrome is removed so the colour swatch fills the entire element. Use alongside a text input for hex/named colour entry.

<div class="block row gap-s align-center">
  <input type="color" id="color-picker" value="#ffa500">
  <input type="text" value="ffa500" placeholder="hex or name">
</div>

Properties: appearance: none, aspect-ratio: 1 / 1, align-self: stretch (matches sibling height), padding: var(--space-xs), swatch wrapper padding removed. Same border and focus styles as text inputs.


Disabled State

Add the disabled attribute to any input, textarea, or select:

<input type="text" value="Cannot edit" disabled>

Properties: background, color, cursor: not-allowed.


Checkbox & Radio

Checkboxes and radios use appearance: none with custom styling. Wrap each in for inline label alignment.

Checkbox

<div class="form-check">
  <input type="checkbox" id="terms">
  <label for="terms">I agree to the terms</label>
</div>

Properties: 24px size (), fill, border with corners. Checked state uses fill with a white checkmark SVG.

Radio

<div class="form-check">
  <input type="radio" name="group" id="option-a">
  <label for="option-a">Option A</label>
</div>

Properties: same as checkbox but with border-radius: 50% and a centered dot on checked.


Toggle / Switch

A toggle is a checkbox styled as a sliding switch. Use instead of . Always include role="switch" for accessibility.

Default (label left)

<div class="form-toggle">
  <input type="checkbox" id="notifications" role="switch">
  <label for="notifications">Enable notifications</label>
</div>

Label right

Add to place the label after the toggle.

<div class="form-toggle is-label-right">
  <input type="checkbox" id="darkmode" role="switch">
  <label for="darkmode">Dark mode</label>
</div>

Disabled

<div class="form-toggle">
  <input type="checkbox" id="feature" role="switch" disabled>
  <label for="feature">Coming soon</label>
</div>

Properties: 44px × 24px pill-shaped track, 18px circular knob. Unchecked: background with knob. Checked: background, knob slides right and becomes .


Layout Patterns

Form Group

Use to wrap a label + input pair with consistent bottom spacing:

<div class="form-group">
  <label for="name">Name</label>
  <input type="text" id="name">
</div>
<div class="form-group">
  <label for="email">Email</label>
  <input type="email" id="email">
</div>

Form Check

Use for inline checkbox/radio + label pairs:

<div class="form-check">
  <input type="checkbox" id="opt-in">
  <label for="opt-in">Subscribe to newsletter</label>
</div>

Properties: display: flex, align-items: center, gap for spacing. The label inside is inline with regular weight.

Fieldset & Legend

Use <fieldset> and <legend> to group related form controls:

Contact details
<fieldset>
  <legend>Contact details</legend>
  <div class="form-group">
    <label for="phone">Phone</label>
    <input type="tel" id="phone">
  </div>
</fieldset>

Segmented Control

is a button group that acts like a single-select input — similar to a group of radio buttons but with a tab-like appearance.

<div class="segmented-control">
  <button class="segmented-control-btn is-active">Option A</button>
  <button class="segmented-control-btn">Option B</button>
  <button class="segmented-control-btn">Option C</button>
</div>

Icon variant

Use on a segment button for icon-only options:

<button class="segmented-control-btn is-icon" aria-label="Grid view">
  <div class="svg-icn" data-icon="grid"><!-- SVG --></div>
</button>

Styling

  • Track: with corners
  • Active segment: background with text
  • Focus: 2px outline with offset

Accessibility

  • Add role="group" and aria-label to the container
  • Use aria-pressed="true" on the active segment button
  • Toggle is-active and aria-pressed via JavaScript on click

Slider

input[type="range"] is styled with design system tokens. Use for a labelled slider with live value display. See the Slider docs for full details.

75%
<div class="slider-wrapper">
  <div class="slider-header">
    <label for="opacity">Opacity</label>
    <span class="slider-value" id="opacity-val">75%</span>
  </div>
  <input type="range" id="opacity" min="0" max="100" value="75"
    oninput="document.getElementById('opacity-val').textContent = this.value + '%'">
</div>

Number Input

wraps a native number input with decrement/increment buttons. See the Number Input docs for full details.

<div class="number-input" role="group" aria-label="Quantity">
  <button class="number-input-btn" data-number-decrement type="button" aria-label="Decrease">&minus;</button>
  <input type="number" value="1" min="0" max="99" aria-label="Quantity">
  <button class="number-input-btn" data-number-increment type="button" aria-label="Increase">+</button>
</div>

Requires assets/js/number-input.js.


Radio Group

wraps multiple radio inputs with consistent spacing. Supports vertical (default) and horizontal () layouts. See the Radio Group docs for full details.

Shipping method
<fieldset>
  <legend class="radio-group-label">Shipping method</legend>
  <div class="radio-group">
    <div class="form-check">
      <input type="radio" name="shipping" id="std" checked>
      <label for="std">Standard (5-7 days)</label>
    </div>
    ...
  </div>
</fieldset>

Usage rules

Do Don't
Use <label> with for attribute Use placeholder as a label replacement
Use for spacing Add margins directly to inputs
Use for checkbox/radio pairs Float labels next to checkboxes manually
Use for toggle switches Style a checkbox as a toggle without the wrapper
Add role="switch" on toggle inputs Use a toggle without the switch role
Use semantic tokens for customization Hardcode colors on individual inputs
Use <fieldset> for logical grouping Use <div> with borders to fake fieldsets
Keep inputs full-width by default Set fixed widths unless layout requires it

CSS reference

This section documents how the component is built. For usage, see the sections above.

Tokens

Token Default What it controls
Default border colour
Input background
Input text colour
Placeholder text colour
Focus border and ring colour
Disabled background
Disabled text colour
Checkbox unchecked background
Checkbox/radio checked fill
Checkbox/radio border colour
Checkmark/dot colour
Toggle track background
Toggle knob (unchecked)
Toggle track (checked)
Toggle knob (checked)

Selectors

Selector Purpose
input[type="text"], input[type="email"], etc. Global text input styling — width, padding, border, font
input:focus, textarea:focus, select:focus Focus state — border colour + box-shadow ring
input:disabled, textarea:disabled, select:disabled Disabled state — muted background, not-allowed cursor
textarea Textarea — min-height, vertical resize
select Select — custom dropdown arrow, appearance reset
input[type="color"] Colour picker — appearance reset, aspect-ratio, swatch styling
input[type="checkbox"], input[type="radio"] Custom checkbox/radio — appearance reset, checked state SVG
Inline checkbox/radio + label wrapper — flex, align-items, gap
.form-check label Label styling inside check wrapper — inline, regular weight
Toggle switch wrapper — grid layout for label + switch
.form-toggle input[type="checkbox"] Toggle track — pill shape, colour transition
.form-toggle input[type="checkbox"]::after Toggle knob — circular pseudo-element
.form-toggle input[type="checkbox"]:checked Checked track — background
.form-toggle.is-label-right label Label-right variant — reorders grid column
Label + input wrapper — bottom margin spacing
Helper text below input
Error message styling
Button group track — faded background, pill radius
Segment button — padding, transitions
.segmented-control-btn.is-active Active segment — primary bg, inverted text
.segmented-control-btn.is-icon Icon-only segment variant
Labelled slider container
Stepper wrapper — flex, border
Increment/decrement button
Radio group wrapper — vertical stack
.radio-group.is-horizontal Horizontal radio layout
Group legend styling
On this page
  • Labels
  • Text Inputs
  • Focus State
  • Textarea
  • Select
  • Colour Input
  • Disabled State
  • Checkbox & Radio
  • Toggle / Switch
  • Layout Patterns
  • Segmented Control
  • Slider
  • Number Input
  • Radio Group
  • Usage rules
  • CSS reference
Previous

Copy Button

Next

Number Input

Was this page helpful?

We use this feedback to improve our documentation.

Thanks for your feedback

Send feedback

© 2026 By Default