Form Patterns
Recipes for real forms: field anatomy, validation, grouped fields, action footers, setting rows, and single-field captures. These aren’t new components. They’re arrangements of Label, Input, Select, Checkbox, Switch, and Button. Copy them into your app and name them for your domain.
Field anatomy
A complete field has three parts: a label, the control, and helper text that sets expectations. Mark optional fields explicitly so required stays the silent default.
Field with error
Validate on blur or submit, then colocate the message directly beneath the field. The red ring (aria-invalid) and the text always travel together: color alone is not an error.
Setting rows
Label and description on one side, control on the other. The whole row is the target, not just the control, so there are no dead zones.
Grouped fields
Related fields share a row and collapse to stacked on narrow screens. Spacing is tighter within a field (label to input) than between fields.
Form with action footer
A real form ends in an action row. The primary action sits on the right with the secondary (Cancel) to its left, both right-aligned where the eye lands after the last field.
Submission state
Disable the submit button while the request is in flight and name the state (Saving…). This prevents duplicate submissions and signals that something is happening.
Single-field capture
The newsletter family: one field, one button. Vary the layout to fit the space and the button copy to fit the ask.
Stacked: the default, works at any width
Inline: field and button on one row, button hugs its label
With icon: a leading glyph replaces the label for unambiguous captures
Custom CTA: the button label does the persuading