Multi-step payments form flow

Confidential financial institution (internal app)

Timeframe: Apr 25 – May 26 • Role: Senior Frontend Engineer (Contract) • Users: Hundreds across ~40 branches

Refined and stabilized a nine-step internal payments flow, improving validation clarity, accessibility, and error visibility in a compliance-sensitive environment.

Checklist (gather these items)

  • Problem statement in 1–2 sentences
  • Constraints (security, compliance, timelines, dependencies)
  • Flow diagram or step list
  • Validation rules + tricky edge cases
  • Accessibility notes (keyboard, labels, errors)
  • Analytics events + what decisions they enabled
  • Performance metrics (before/after)
  • Testing strategy (unit/integration/e2e)
  • Outcome + learnings

Highlights

  • Standardized validation behavior and error presentation across 9 steps.
  • Prevented stale/invalid combinations by explicitly clearing dependent fields when upstream selections changed.
  • Improved keyboard and assistive-technology usability with consistent semantics and error announcements.

The problem

  • A 9-step, full-page payments flow layered on top of an MVP had accumulated validation inconsistencies.
  • Errors were often opaque or surfaced late, increasing cognitive load and rework.
  • Conditional business rules made it easy for stale or invalid data to persist across steps.
  • Accessibility needed review to ensure the flow worked with keyboard and assistive technologies.

Users & jobs-to-be-done

  • Internal bank employees (hundreds of users across ~40 branches)
  • Enter and submit payment details accurately
  • Understand validation issues immediately and correct them in place
  • Complete submissions confidently without hidden errors

Constraints

  • Compliance: financial data, PII, audit expectations
  • Scope: refinement on top of MVP v1
  • Backend: Java multi-service backend owned by another team
  • Design system: MUI components
  • Internationalization required (localized strings + validation)
  • CI/CD: Jenkins on bare metal with limited access

Baseline

  • Validation rules varied by step and were not always clearly surfaced
  • Some dependent fields could retain invalid values after upstream changes
  • Accessibility had not yet been reviewed end-to-end
  • Error rates were not instrumented, making improvements qualitative rather than quantitative

My responsibilities

  • Owned frontend refinement of the 9-step form flow
  • Standardized validation behavior and error presentation
  • Implemented conditional rendering and requiredness based on business rules
  • Coordinated async backend validation with clear UI feedback and recoverable states
  • Led an accessibility review and applied recommendations
  • Ensured all changes were i18n-safe and compliant

The solution

UX

  • Full-page, step-based flow with clear progression
  • Validation errors surfaced immediately at the field/step level
  • Review step before final submission

State model

  • Centralized form state using React Hook Form
  • Forward navigation gated by validation; backward navigation allowed
  • No autosave (explicitly deferred due to compliance considerations)

Validation

  • Charge Account-driven rules:
    • Customer Account: Account Number required; Transit Number required and rendered
    • Other Account: Account Number required; Transit Number not required and not rendered
  • Dependent values (Transit/Account) cleared when Charge Account changes to prevent stale data
  • Numeric normalization on blur:
    • Transit Number padded to 4 digits
    • Account Number padded to 7 digits
  • Async backend validation for account existence/correctness, with recoverable error states

Error design

  • Differentiated formatting errors vs backend validation failures
  • Explicit, user-actionable error messages
  • Graceful fallback paths when backend validation fails

Accessibility

  • ARIA attributes used consistently (labeling + descriptions)
  • Semantic HTML and heading hierarchy applied
  • Keyboard navigation verified across steps and dialogs
  • Dialogs announce correctly to screen readers and trap focus
  • Validation errors associated with inputs and announced

Internationalization

  • All labels and validation/error copy localized
  • Validation logic designed to be locale-agnostic

Analytics & instrumentation

No formal KPIs were tracked during this refinement phase. Improvements were assessed via:

  • Manual QA
  • Reduced ambiguity during error handling
  • Qualitative UX feedback from internal users

Testing strategy

  • Unit/integration: Vitest for form and validation logic
  • Static analysis: ESLint with strict expectations
  • Quality gates: SonarQube (~80% coverage requirement)
  • Manual testing: step navigation, validation edge cases, keyboard flows

Results

  • Validation errors surfaced earlier and more clearly
  • Reduced likelihood of submitting stale or invalid data
  • Improved usability for keyboard and assistive-technology users
  • Strong qualitative UX improvement reported by stakeholders

Tradeoffs & decisions

  • Deferred autosave to avoid unintended persistence of financial data
  • Chose explicit clearing of dependent fields over implicit state retention
  • Accepted qualitative UX validation due to lack of analytics instrumentation
  • Focused on refinement/correctness rather than expanding scope beyond MVP

Edge cases handled

  • Charge Account changes invalidating downstream fields
  • Partial numeric input with automatic normalization
  • Backend validation failures with manual-review fallback
  • Localization of validation messages
  • Keyboard-only navigation across all steps and dialogs

What I’d do next

  • Add step-level analytics to quantify drop-off and error frequency
  • Implement session-scoped autosave with compliance review
  • Perform formal assistive-technology testing (NVDA, VoiceOver)
  • Add targeted e2e tests for critical payment paths

Notes on redaction

Company names, internal tools, and screenshots are anonymized. Validation rules and flow behavior are preserved without exposing sensitive details.