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.
<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
<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.
.field.field-label.field-required.field-hint.input.textarea.select.swatch.field-affixed.field-affix.field-foot--field-shadow β falls back to --ds-shadow-flat--swatch-w β falls back to --ds-swatch-w--swatch-h β falls back to --ds-swatch-h--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-metaNotes
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.
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.