Field

Shipping address form

Long forms use .field-group (a borderless fieldset) to stack fields. Wrap fields in a <div> inside the group to split them into equal columns. The columns fold into one on narrow screens.

Edit shipping address

Destination country
House number and street
e.g. leave at the front desk

Invalid field and a checkbox beside its label

Set aria-invalid="true" on the input to turn its border and hint danger. Link the error with aria-describedby. A checkbox placed before its label in a .field lays out as a row.

Billing address
Enter a 5 digit ZIP code

Checkbox: plain, with help text, disabled, whole row as label

For longer text, put the label and a <small> in a <div> after the checkbox. To make the whole row clickable, wrap it all in <label class="field">. Add data-variant="card" for a border.

By ticking this you agree to the terms

Partly ticked (select all)

HTML cannot set the indeterminate state. A script has to set checkbox.indeterminate = true. This example is a select-all checkbox that controls a product's variants. The browser draws the dash itself.

1 of 3 variants selected

Radio

Wrap radios in <fieldset class="field-group" data-gap="sm"> with a <legend> so screen readers announce the group name. Arrow keys move between options natively.

Table density

Switch

A checkbox with role="switch" draws as a switch. Use it for settings that apply at once. It works inside a .field or on its own.

$2.00 fee per order

Slider

<input type="range" class="slider"> uses its own min, max, step and value as usual. The script fills the track up to the thumb and writes the value into any <output for="id"> that points to it.

API

The slider uses js/slider.js (other fields need no JS). It also works on .slider elements added later.

Member Args Description
--value Custom property on the input: the current value as a percentage (e.g. 30%). The accent fill is this wide. Set it in style yourself if you don't load the JS.
output[for] The script writes value into every <output> whose for contains the slider's id.
window.tsunami.slider.sync(el) el el is an input.slider. Redraws the fill and outputs. Call it after setting el.value from script (script changes don't fire an input event).
input The input's own event. The script redraws on every move and after a form reset.

Attributes

Attribute / element Values Description
.field Wraps a label, input and hint in a vertical stack. With a checkbox or radio as the first child, it lays out as a row.
.field > label Small muted label (normal colour in a checkbox row)
.field > small Hint or error text. Link it to the input with aria-describedby.
.field > input / select / textarea Styled like .input without the class (see the Input page).
.field > div In a checkbox row: stacks the label and small (or h3).
aria-invalid true On the input: border and small turn danger
disabled On the input: row label turns muted, cursor not-allowed
data-variant card (none = default) On label.field: a border around the whole row. The background changes when ticked.
role switch On input type=checkbox: draws a switch. Works anywhere.
.slider On input[type=range]: track and thumb use the colour variables. See the API above.
.field-group Borderless fieldset or div[role=group]. Stacks fields space-4 apart.
.field-group > legend Group heading (bold). With data-gap="sm" it is a small muted label.
.field-group > div A div with no class splits its fields into equal columns, each at least 9rem wide.
data-gap sm (none = space-4) On .field-group: tight spacing for checkbox, radio and switch lists.