Skip to content

COMPONENT

Field

A labelled control with a hint, and the five states it can be in. The wrapper holds the state, and the label, the control and the hint all read it from there.

The states

Click into the first one β€” focus moves the border and the label into the accent together.

Placeholder text sits at ink-faint.

Value steps up to ink-read.

That address is missing a domain.

Dropped a step, never greyed out entirely.

HTML
<div class="field">
  <label class="field-label" for="f-default">DEFAULT <span class="field-required">*</span></label>
  <input class="input" id="f-default" type="email" placeholder="[email protected]">
  <p class="field-hint">Placeholder text sits at ink-faint.</p>
</div>
<div class="field">
  <label class="field-label" for="f-filled">FILLED</label>
  <input class="input" id="f-filled" type="email" value="[email protected]">
  <p class="field-hint">Value steps up to ink-read.</p>
</div>
<div class="field">
  <label class="field-label" for="f-error">ERROR</label>
  <input class="input" id="f-error" type="email" value="ada@analytical"
         aria-invalid="true" aria-describedby="f-error-hint">
  <p class="field-hint" id="f-error-hint">That address is missing a domain.</p>
</div>
<div class="field">
  <label class="field-label" for="f-disabled">DISABLED</label>
  <input class="input" id="f-disabled" type="text" value="Locked while sending" disabled>
  <p class="field-hint">Dropped a step, never greyed out entirely.</p>
</div>

Textarea, select, a colour and an affix

Markdown is fine.148 / 1000
https://
HTML
<div class="field" style="grid-column:1/-1">
  <label class="field-label" for="f-area">TEXTAREA</label>
  <textarea class="textarea" id="f-area">Two paragraphs is plenty. Tell me what you are building, what has already been tried, and the date that actually matters.</textarea>
  <div class="field-foot"><span>Markdown is fine.</span><span>148 / 1000</span></div>
</div>
<div class="field">
  <label class="field-label" for="f-select">SELECT</label>
  <select class="select" id="f-select">
    <option>Retainer</option>
    <option>Project</option>
    <option>Advisory</option>
  </select>
</div>
<div class="field">
  <label class="field-label" for="f-colour">A COLOUR</label>
  <div class="cluster">
    <input class="swatch" id="f-colour" type="color" value="#7fb2d0" />
    <input class="input" type="text" value="#7fb2d0" aria-label="The same colour as a hex value" />
  </div>
</div>
<div class="field">
  <label class="field-label" for="f-prefix">WITH PREFIX</label>
  <div class="field-affixed">
    <span class="field-affix">https://</span>
    <input class="input" id="f-prefix" type="text" value="yourdomain.com">
  </div>
</div>

Reference

Read from components/field.css when this page was built, so it cannot fall behind the stylesheet.

CLASSES.field.field-label.field-required.field-hint.input.textarea.select.swatch.field-affixed.field-affix.field-foot
SETTINGSSet the first on one element; a theme sets the second for all of them.--field-shadow β€” falls back to --ds-shadow-flat--swatch-w β€” falls back to --ds-swatch-w--swatch-h β€” falls back to --ds-swatch-h
READS--ds-accent--ds-chevron-leg--ds-focus-ring--ds-focus-width--ds-font-body--ds-font-display--ds-gap-loose--ds-gap-tight--ds-ground--ds-hairline--ds-ink--ds-ink-disabled--ds-ink-faint--ds-ink-read--ds-motion-fast--ds-pad-control--ds-pad-shell-inline--ds-radius-field--ds-rule--ds-rule-strong--ds-select-chevron-space--ds-shadow-well--ds-state-error--ds-sunk--ds-swatch-inset--ds-text-control--ds-text-label--ds-text-meta--ds-text-ui--ds-textarea-h--ds-track-meta

Notes

ERROR IS aria-invalid, NOT A CLASS

A class can say a field is invalid while assistive technology is told nothing, and that is the failure that matters most here. Styling the attribute means the two cannot disagree. Pair it with aria-describedby pointing at the hint, so the reason is announced along with the state.

The hint takes the error colour with it. A red border above a grey explanation makes the reader hunt for what is actually wrong.

THE SWATCH IS A FOURTH CONTROL, NOT A FOURTH DRAWING

It takes no padding, no colour and no full width, so it cannot join the rule that draws input, textarea and select. It is in both of the lists below that one, though β€” focus and disabled are states, and a control whose states are written separately is a control whose states drift.

The panel it opens is the browser's and nothing here reaches it. The box is not, which is the half of that argument this library got wrong for months β€” see Range.

TWO MORE RULES

LABEL INSIDE THE WRAPPERso :focus-within can reach it
PLACEHOLDER IS NOT A LABELit vanishes when you type