Skip to content

Form validation

Preview Available in release assets

Present native constraint validation and authoritative server errors without moving business rules into a design-system script.

Server contract

POST /api/advanced/form-validation accepts the canonical native form and returns a complete document; GET the same route renders the initial document. Add .thin-form-validation to the form and .thin-validation-summary to a server-rendered summary. A Datastar request to the same action returns one patch replacing the stable form, while server business validation remains application code.

With no CSS, JavaScript, or Datastar, the form posts to its action and the server returns a complete document containing submitted values and errors. Native constraint validation remains available, while server validation is always authoritative.

Form validation primary example

Show code
<form class="thin-form-validation" action="/account/profile" method="post">
  <div class="thin-validation-summary" role="alert" aria-labelledby="profile-errors-title">
    <h2 id="profile-errors-title">There is a problem</h2>
    <ul>
      <li><a href="#profile-email">Enter an email address in the correct format.</a></li>
    </ul>
  </div>
  <div class="thin-field">
    <label for="profile-name">Display name</label>
    <input class="thin-input" id="profile-name" name="display_name" required minlength="2" maxlength="80" autocomplete="name" value="A very long submitted name remains available for correction" />
  </div>
  <div class="thin-field">
    <label for="profile-email">Email address</label>
    <input class="thin-input" id="profile-email" name="email" type="email" required autocomplete="email" value="not-an-email" aria-invalid="true" aria-describedby="profile-email-hint profile-email-error" />
    <small class="thin-hint" id="profile-email-hint">Used for account notices.</small>
    <small class="thin-error" id="profile-email-error">Enter an email address in the correct format.</small>
  </div>
  <button class="thin-button" type="submit">Save profile</button>
</form>

Each authored example uses the production assets and includes copyable markup.

Anatomy

  • Ordinary method and action
  • Optional linked error summary
  • Labelled native controls
  • Persistent hints
  • Field-level server errors
  • Submit button

Variants and sizes

  • Native constraint validation — shown above
  • Server-rendered field errors — shown above
  • Linked error summary — shown above
  • Datastar-enhanced server response — shown above

Rendered fixtures exercise authored content and constrained layouts with the same production assets.

  • Pristine
  • User-invalid native constraint
  • Server-rejected submission
  • Multiple errors
  • Corrected resubmission
  • Long localized message
  • Narrow container
  • Network or enhancement failure

Structured state fixtures are not published for this item yet.

Interaction and keyboard behavior

The browser checks authored type, required, min, max, minlength, maxlength, and pattern constraints before ordinary submission. The server revalidates every value and returns the submitted values plus specific errors. An optional Datastar flow may morph the same server-authored form, then focus the summary; it must not change the rules or response meaning.

Accessibility

Keep errors in text and associate field errors through aria-describedby without discarding hints. Set aria-invalid only for a known invalid value. Give a returned summary a heading, link each message to its control, and move focus to it only after a submitted response—not during typing. Do not rely on color, live validation, or disabled submit buttons.

Contract
LIVE
Basis
Native form constraint validation plus authored summary/status; no APG widget
Evidence
  • tests/unit/library/date-time-validation.test.ts

API

POST /api/advanced/form-validation accepts the canonical native form and returns a complete document; GET the same route renders the initial document. Add .thin-form-validation to the form and .thin-validation-summary to a server-rendered summary. A Datastar request to the same action returns one patch replacing the stable form, while server business validation remains application code.

Behavior tier: datastar-optional

Structured host, property, and example tables are not authored for this item yet. Use the summary above and the primary example.

Fallback

The native form posts to its server action and returns complete errors without JavaScript.

Assets and dependencies

  • /components.css

Dependencies: None

Source: packages/ui/src/items/form-validation/style.ts

Composition

Derived from the examples and style specs, not authored.

Composes