DEVELOPMENT PREVIEWIn development

Forms & Validation

Problems are caught before submission and shown inline at the fields — not collected in a summary box, not thrown as toasts. Submit the empty form to see it.

Plan
At least 10 characters.

How this works

Every control just has a name — no controlled state, no error threading. The Form runs browser constraint validation first (required, type="email"…), then the zod-backed validate functions, and renders each problem under its own field. After the first attempt, errors clear live as you fix them.

Snippet
const email = z.string().email('Enter a valid email address.')
const zodMessage = (schema, value) => schema.safeParse(value).error?.issues[0]?.message

<Form
  validate={{ email: value => zodMessage(email, value) }}
  onSubmit={values => api.contact(values)}
>
  <TextInput name="email" label="Email" type="email" required />
  <Checkbox name="agree" label="I agree to the terms" required />
  <Button type="submit">Submit</Button>
</Form>

Full contract — focus management, cross-field rules, custom controls — on the Form page.