Barefoot CSS v7.4

Form Architecture

The async validation contract, a wizard stepper, the conditional-field boundary, field arrays, and upload progress. The app owns the state; the tokens and the platform present it.

Back to the conformance demo · states & events · data story · the contract.

Async validation

A field whose value is checked somewhere else. The app debounces on input, sets data-async-pending + aria-busy while the check is in flight, and lands the failure on the same surface as a native error. Try ada (taken) or anything else (free) — and notice a too-short value never fires the check: native pattern answers first.

That one is taken. Try another.

Contract

<div class="bf-form-group" data-async-pending aria-busy="true"> …<small class="bf-async-text" role="status">Checking availability…</small> …<small class="bf-error-text" role="alert">That one is taken.</small> </div>

Wizard / stepper

A stepper plus one panel per step. aria-current="step" is single-valued and moves in the same handler that swaps the panel; panels are hidden with hidden, never removed, so back preserves input. Next validates the panel it leaves using native constraint validation.

  1. 1Account
  2. 2Profile
  3. 3Review

Account

The conditional boundary

One observed fact is one selector — pure CSS is right. Field B shows iff Field A checked needs no script:

The moment the condition is not a single observed fact — billing shows iff same-as-shipping is unchecked and the country is Germany and the plan is paid — stop. A three-deep :has() chain recalculates on every keystroke and cannot be read. JS sets data-state; CSS only reveals:

form[data-ready="de-pro"]:has(#fa-plan[value="pro"]:checked) [data-de-fields] { display: block; }

Field array

"Add another phone." The array is JS-owned — append, remove, renumber, and move focus off a doomed row — CSS only aligns.

Phone numbers

Upload progress

The async contract at file scale: the row is pending while the upload runs, the live region narrates it, and a themed <progress> bar carries the shape readers can see.

Event log