Inaccessible signup and onboarding flows violate WCAG 2.2 SC 1.3.1 (Info and Relationships), 2.1.1 (Keyboard), 2.4.3 (Focus Order), 2.4.11 (Focus Not Obscured), and Section 508 §502.3 — and expose the company to ADA Title III litigation risk in the US. Form fields without labels are unusable with a screen reader; missing role="alert" means error messages are invisible to assistive technology. These aren't cosmetic gaps: they legally and functionally exclude users with disabilities from your product at the first interaction.
Critical because inaccessible onboarding is both a legal exposure under ADA/Section 508 and a hard blocker for users who rely on screen readers or keyboard navigation to complete signup.
In src/app/(auth)/signup/page.tsx, associate every input with a visible label and link errors via aria-describedby:
<div>
<Label htmlFor="email">Email</Label>
<Input
id="email"
type="email"
aria-describedby={emailError ? "email-error" : undefined}
/>
{emailError && (
<p id="email-error" role="alert" className="text-destructive text-sm">
{emailError}
</p>
)}
</div>
Audit every outline: none in your global CSS — either remove it or add a visible :focus-visible replacement. For modal dialogs, use a focus trap library (focus-trap-react) so keyboard users can't tab outside the dialog.
ID: saas-onboarding.onboarding-ux.accessibility-of-onboarding
Severity: critical
What to look for: Count all form fields in signup and onboarding. For each, classify whether it has an associated <label> or aria-label. Count error messages and check for aria-describedby or role="alert". Enumerate interactive elements and verify keyboard navigability. Check focus management in modals. Count outline: none usages.
Pass criteria: 100% of form fields in signup have an associated <label> or aria-label. Error messages use aria-describedby or role="alert". All interactive elements are reachable via keyboard. No outline: none without a visible focus replacement. Report even on pass: "Checked N form fields — all have labels. N error states use role=alert."
Fail criteria: Any of: form fields without labels or aria-label; error messages that only appear visually with no role="alert"; interactive elements not reachable by keyboard; focus not trapped in modal dialogs; focus indicators removed with outline: none and no visible replacement.
Skip (N/A) when: The project has no user-facing UI (API-only, CLI tool, or library).
Detail on fail: List specific failures. Example: "Signup form: email and password fields have no associated <label>. Error messages have no role='alert'. Modal dialog does not trap focus. Tab order skips the 'Show password' toggle."
Remediation: In your signup form at src/app/(auth)/signup/page.tsx:
<div>
<Label htmlFor="email">Email</Label>
<Input id="email" type="email" aria-describedby={error ? "email-error" : undefined} />
{error && <p id="email-error" role="alert" className="text-destructive text-sm">{error}</p>}
</div>
Cross-reference: For a comprehensive accessibility review across the full application, the Accessibility Fundamentals Audit covers WCAG 2.1 AA compliance in depth.