Forms
Text entry, and the wrapper that gives it a label, a hint and an error. Every control shares one focus treatment — an accent border plus a --ring-w ring in --ring — so a form looks like one thing. Checkboxes, radios and the toggle switch are on Selection controls.
The field
_78-field wraps a label, a control and an optional hint or error, and supplies the
spacing between fields. A <label> directly inside it is styled automatically.
<div class="_78-field">
<label for="f-1">Workspace name</label>
<input class="_78-input" id="f-1" type="text" placeholder="Acme Design">
<div class="_78-field-hint">Click into it — accent border plus the focus ring.</div>
</div>
Labels outside a field
_78-label is the same label styling as a standalone class, for a label that is not a
direct child of _78-field — a label above a group, or one inside your own layout.
<span class="_78-label" id="notify-label">Notify me about</span>
<div role="group" aria-labelledby="notify-label">
<label class="_78-check"><input type="checkbox"> Mentions</label>
<label class="_78-check"><input type="checkbox"> Replies</label>
</div>
Rows
_78-field-row puts fields side by side, each flexing from a 180px basis, so they stack
on their own on a narrow screen.
<div class="_78-field-row">
<div class="_78-field">
<label for="f-2">Plan</label>
<select class="_78-select" id="f-2">
<option>Starter</option><option>Team</option><option>Enterprise</option>
</select>
</div>
<div class="_78-field">
<label for="f-3">Seats</label>
<input class="_78-input" id="f-3" type="number" value="24" step="1">
</div>
</div>
Inline form
Some forms are one field and a button: dismiss with a reason, add a row, a quick filter.
_78-form-inline puts them on one row with their bottoms aligned, so the button sits level
with the input under its label. Fields flex from a 180px basis and drop their bottom margin; buttons,
checkboxes and switches keep their size. On a phone the row wraps.
Its natural home is a card foot, which already gives it the padding and the rule above — no classes of your own:
Watched since Sep 14 for a renewal at the new price.
<div class="_78-card">
<div class="_78-card-title">Northwind</div>
<p class="_78-text-dim">Watched since Sep 14 for a renewal at the new price.</p>
<div class="_78-card-foot">
<form class="_78-form-inline">
<div class="_78-field">
<label for="dismiss-why">Why (optional)</label>
<input class="_78-input" id="dismiss-why" name="reason" maxlength="500" autocomplete="off">
</div>
<button class="_78-btn" type="submit">Dismiss</button>
</form>
</div>
</div>
<form class="_78-form-inline">
<div class="_78-field">
<label for="add-name">Name</label>
<input class="_78-input" id="add-name" placeholder="Account name">
</div>
<label class="_78-check"><input type="checkbox"> Notify me</label>
<button class="_78-btn _78-btn-primary" type="submit">Add</button>
</form>
| Class | What it does |
|---|---|
_78-form-inline | A wrapping flex row, bottoms aligned, --space-3 apart. |
> _78-field | Flexes from 180px; no bottom margin. |
> _78-btn, _78-btn-group | Keep their size, level with the input. |
> _78-check, _78-switch | Keep their size, centered on the input's line. |
Put a hint or an error after the form, not inside a field: a line under one input pushes the button out of line with it.
Controls
Three control classes cover the native inputs. They share hover, focus and disabled treatments.
<div class="site-demo-block">
<div class="_78-field">
<label for="f-4">Text input</label>
<input class="_78-input" id="f-4" type="text" placeholder="Placeholder text">
</div>
<div class="_78-field">
<label for="f-5">Select</label>
<select class="_78-select" id="f-5"><option>Choose one</option><option>Or the other</option></select>
</div>
<div class="_78-field">
<label for="f-6">Textarea</label>
<textarea class="_78-textarea" id="f-6" placeholder="Anything the team should know…"></textarea>
</div>
<div class="_78-field">
<label for="f-7">Disabled</label>
<input class="_78-input" id="f-7" type="text" value="Locked by your plan" disabled>
</div>
</div>
Validation
Two ways to mark a control invalid, and they are not equivalent.
aria-invalid="true" is the one to reach for: it colors the border
and tells assistive technology the value is rejected. _78-invalid is the
class-only fallback for when you cannot set the attribute — it looks identical but says nothing
to a screen reader.
Either way, point at the message with aria-describedby so it is announced with the field
rather than sitting there unread.
<div class="site-demo-block">
<div class="_78-field">
<label for="f-8">Seats</label>
<input class="_78-input" id="f-8" type="text" value="-4"
aria-invalid="true" aria-describedby="f-8-err">
<div class="_78-field-error" id="f-8-err">Must be a positive number.</div>
</div>
<div class="_78-field">
<label for="f-9">Seats</label>
<input class="_78-input _78-invalid" id="f-9" type="text" value="-4">
<div class="_78-field-error">Same look, but nothing is announced.</div>
</div>
</div>
aria-invalid also drives the focus treatment, so an invalid field keeps its red border
while focused instead of reverting to the accent.
Checkboxes, radios and the switch moved
_78-check for checkboxes and radios, and
_78-switch for the toggle — are documented on
Selection controls, with every
variant and the same live examples.