Context

A contact form should feel lightweight and calm, but behave like a real product UI: predictable states, clear feedback, and accessibility.

Decisions

  • Global status + field-level errors
    Provide a summary message and point to the exact fields.
  • Correct aria-live behavior
    Use polite updates for info and assertive updates for errors.
  • Keep the form visible after success
    Dim or “soft-collapse” fields instead of hiding the entire form.

Implementation notes

  • Use an in-flight guard to prevent double submits.
  • Clear field errors on input changes.
  • Reset Turnstile on relevant error paths to avoid stale tokens.

Lessons learned

Good UX is a combination of behavior, wording, and a11y — not just styling.