Docs / Guide: Forms, For Real

Guide: Forms, For Real

Validation timing, the submit path, and errors that teach — the unglamorous decisions that make a form trustworthy.

Start from the Field

Every control on the page is a Field: label, control, hint, error, in that order, always. The order is the accessibility contract — a screen reader meets the label before the control, and the hint is wired to the input with aria-describedby before any error exists. If a form needs a paragraph of instructions above it, the fields are under-labelled; move the words into the hints, where they are read at the moment of need.

Required is marked in the label, not discovered at submit. Optional fields in a sea of required ones say "optional" — pick one convention and let the mold hold it.

When to validate

On blur, for format; on submit, for everything; on input, only to clear an error already shown. Validating on the first keystroke punishes people mid-word, and validating only at submit makes them hunt. The error appears under the field it belongs to and replaces the hint rather than pushing the layout down — the page must not jump while someone is reading it.

A format the site can fix, it fixes silently: spaces in a card number, a phone number without its dashes. Correction without a scolding is the friendliest validation there is.

The submit path

The click disables the button and changes its label to the verb in progress — "Saving…", not a spinner alone. Success moves focus to the confirmation (a Toast for a small save, a new page for a big one) and failure keeps every value exactly where the user left it, with the summary at the top naming how many fields need attention and linking to each. A form that eats input on failure will be abandoned on the second failure, correctly.

Double-submit is a client bug before it is a server problem: the disabled state is part of the part, not a courtesy.

Errors that teach

An error names the field, the problem and the fix in one breath: "Expiry is in the past — enter a future date", never "Invalid input". Errors are written for someone already frustrated, possibly on a phone, possibly in a second language. Short, concrete, and free of blame are not softness; they are what makes the next attempt succeed.

More docs

Introduction · Getting Started · CLI · Theming · Dark Mode · Accessibility · Installation · Plain HTML · Astro · Laravel · React & Next.js · JavaScript · Guide: Building a Dashboard · Guide: Building a Settings Page · Guide: Building a Pricing Page · Guide: Sign-in & Account Pages · Guide: Data Tables That Survive Real Data · AI Prompts · Why Vanilla · The Mold · Anatomy of a Part · Coming from Tailwind · KATA vs shadcn/ui · FAQ · Registry · Forms · MCP Server · RTL · Contributing · Changelog

    Highlight a part to see it live.