Field chrome
Every field-shaped component renders its own label (above), an optional
right-aligned aside in the label row, and error + description rows below — via one shared FieldChrome. This page shows
the concept + cross-component alignment on Input; each control's own demo has a #field-chrome section. Spec: src/lib/components/FieldChrome.spec.md.
Label + description
Label aside
A right-aligned snippet in the label row — a char count, status, link, or button.
Controlled error
Sets the inline error row + error border + aria-invalid. The description stays visible beneath it.
Required + validate (native tooltip)
required adds the * + aria-required. validate keeps its native-tooltip channel — which fires on submit (or reportValidity()), so it lives in a <form>. Submit it empty
(native required) or with 1–2 characters (the validate message) to see
the browser bubble; the error border is shared with the inline-error path.
Aligned row
Label-above + size-driven control height means a row of mixed controls lines up pixel-perfect — Input, Select, Toggle, and Checkbox all share the same label row + control baseline.
Field background
On a non-white surface, non-ghost fields now fill with --ui-color-background (they read as fields); ghost stays transparent.
Groups — FieldGroup
One wrapper for a set of Radios, Checkboxes, or Toggles under a shared legend. Items render their
label inline (right of the control). For radios, bind the group's value — children need no bind:group. Checkboxes/toggles stay independent.
Selected method: email · caps: webhook