Forms
Wrap a control in a <label> and it is styled. No classes for the common cases.
Text inputs
<label>Name <input type="text" placeholder="Jane Doe" /></label>
<label>Email <input type="email" placeholder="jane@example.com" /></label>
<label>Password <input type="password" placeholder="••••••••" /></label>
<label>Phone <input type="tel" placeholder="503-555-0100" /></label>
<label>Website <input type="url" placeholder="https://example.com" /></label>
<label>Search <input type="search" placeholder="Search" /></label>
<label>Quantity <input type="number" value="1" min="0" /></label>
Label structure
A bare text node in the label works. Wrapping it in <p> gives you a block you
can style, and it is what the invalid-state selector keys off of.
<label>
<p>Birth date</p>
<input type="date" />
</label>
<label>
<p>Reminder</p>
<input type="time" />
</label>
Date, time, and select controls get an icon from --icon-calendar,
--icon-clock, and --icon-chevron. Each is an inline base64 SVG that
swaps between a black and white stroke with the color scheme. Size and inset come from
--icon-width and --icon-position.
Select and textarea
<label>
Role
<select>
<option value="">Select a role</option>
<option>Developer</option>
<option>Designer</option>
<option>Project manager</option>
</select>
</label>
<label>
Bio
<textarea placeholder="Tell us about yourself"></textarea>
</label>
Checkboxes and radios
Put the control inside the label, before the text.
<label><input type="checkbox" /> Subscribe to updates</label>
<label><input type="checkbox" checked /> Already subscribed</label>
<label><input type="radio" name="plan" checked /> Free plan</label>
<label><input type="radio" name="plan" /> Pro plan</label>
Helper text
A <small> immediately after a control collapses the control's bottom margin
and becomes helper text at --text-lc-3.
<label>
Username
<input type="text" />
<small>Letters, numbers, and underscores only.</small>
</label>
Validation
Set aria-invalid="true" on the control. The label's <p> and the
control both pick up --error-color. Pair it with small.error.
<label>
<p>Username</p>
<input type="text" value="taken_username" aria-invalid="true" />
<small class="error">This username is already taken.</small>
</label>
<label>
<p>Password</p>
<input type="password" aria-invalid="true" />
<small class="error">Must be at least 8 characters.</small>
</label>
Disabled and readonly
<label>
Locked field
<input type="text" value="Cannot edit" disabled />
</label>
<label>
Read only
<input type="text" value="Can select, cannot edit" readonly />
</label>
Fieldsets
<fieldset>
<legend>Contact info</legend>
<label>Name <input type="text" /></label>
<label>Email <input type="email" /></label>
</fieldset>
Kitchen sink
Everything above, in one realistic form.
<form>
<fieldset>
<legend>Contact info</legend>
<label>Name <input type="text" placeholder="Jane Doe" /></label>
<label>Email <input type="email" placeholder="jane@example.com" /></label>
<label>
<p>Phone</p>
<input type="tel" aria-invalid="true" />
<small class="error">Enter a valid phone number.</small>
</label>
</fieldset>
<fieldset>
<legend>Preferences</legend>
<label>
Favorite language
<select>
<option>TypeScript</option>
<option>Go</option>
<option>CSS</option>
</select>
</label>
<label><input type="checkbox" /> Send me updates</label>
<label><input type="radio" name="tier" checked /> Free</label>
<label><input type="radio" name="tier" /> Pro</label>
</fieldset>
<label>
Message
<textarea></textarea>
<small>Markdown is supported.</small>
</label>
<div class="flex">
<button type="reset" class="secondary">Reset</button>
<button type="submit">Submit</button>
</div>
</form>