Docs / Forms

Forms

How forms compose in KATA: the field wrapper, honest errors, and which part takes which job.

The shape of a field

Every control wears the same wrapper — the Field part: a label above, the control, then a hint or an error below, in that order, always. The wrapper is what makes a column of different controls read as one form:

<div class="field" data-field>
  <label for="email">Email</label>
  <input class="input" id="email" type="email" autocomplete="email">
  <p class="hint">The receipt goes here.</p>
</div>

Labels are text, never placeholders doing double duty: a placeholder disappears exactly when the reader needs it most.

Errors that say something

An error replaces the hint, in the danger color and in words: what is wrong and how to fix it ("Enter the address the receipt should go to", not "Invalid"). Three wirings make it real rather than decorative: the control carries aria-invalid="true"; the error paragraph has an id the control names in aria-describedby; and on submit, focus moves to a summary at the top listing the problems, each linked to its field.

<div class="field" data-field>
  <label for="email">Email</label>
  <input class="input errb" id="email" type="email" aria-invalid="true" aria-describedby="email-err">
  <p class="err" id="email-err">Enter the address the receipt should go to.</p>
</div>

Never let color be the only signal: the words carry the error for everyone, the red just helps find them.

Grouping and choosing

Choices that belong together get a fieldset with a legend — the Radio and Checkbox groups are built that way — because "how did you hear about us" is the label for the whole set, not for any one option. Which control takes the job: one short line is an Input, a paragraph is a Textarea, one of two-to-five visible options is Radio or Segmented, one of many is a Select or a Combobox, a date is a Date Picker, a time is a Time Picker, several values are a Tag Input, a path down a tree is a Cascader, and assigning many things at once is a Transfer.

Attached pieces stay attached: money gets an Input Group (the ¥ is part of the control, not a caption), and the form’s actions are a right-aligned row of Buttons — the primary one once, at the end.

Required, honestly

Mark required fields in the label text ("Email (required)") or mark the optional ones — pick one convention per form and keep it. Star-only marking fails everyone who cannot see the star’s legend, and there is always a legend nobody reads.

More docs

Introduction · Getting Started · CLI · Theming · Dark Mode · Accessibility · Installation · Plain HTML · Astro · Laravel · JavaScript · Guide: Building a Dashboard · Guide: Building a Settings Page · Guide: Building a Pricing Page · Guide: Sign-in & Account Pages · Why Vanilla · The Mold · Anatomy of a Part · Coming from Tailwind · FAQ · Registry · MCP Server · RTL · Changelog