Skip to content

[FE-31] Accessibility Audit & WCAG 2.1 AA Compliance #1023

@mftee

Description

@mftee

Overview

The platform currently has no accessibility audit, no skip-to-content link, missing ARIA labels on interactive components, and no keyboard navigation testing. Accessibility is a legal requirement in many jurisdictions and is a contributor to SEO. This issue brings the platform to WCAG 2.1 Level AA compliance.

Technical Details

1. Audit Tooling

Install axe-core for automated accessibility testing:

npm install -D @axe-core/react axe-playwright

Add a CI step (or Vitest test) that runs axe against the main routes in JSDOM and reports violations.

2. Global Fixes

Apply across the entire application:

Skip-to-Content Link (frontend/app/layout.tsx):

<a href="#main-content" className="skip-link sr-only focus:not-sr-only">Skip to main content</a>
<main id="main-content">...</main>

Focus management:

  • All modal dialogs must trap focus (use @radix-ui/react-dialog if not already — check Radix is installed)
  • After closing a modal, focus must return to the triggering element
  • Keyboard navigation: all dropdowns and custom components must be keyboard-operable

Color contrast:

  • All text must meet 4.5:1 contrast ratio against its background
  • Audit all text-gray-400 and text-gray-300 instances against white/light backgrounds — increase to text-gray-600 where needed

Images:

  • All <img> elements and <Image> components must have descriptive alt text
  • Decorative images should have alt=""

3. Form Accessibility

Audit all forms in the application:

  • Every <input> must have an associated <label> (via htmlFor / id — not just placeholder)
  • Required fields must have aria-required="true"
  • Validation error messages must use role="alert" or aria-live="polite" so screen readers announce them
  • Form groups (e.g., star rating, radio groups) must have role="group" with aria-labelledby

4. Navigation Landmarks

  • Sidebar navigation must use <nav aria-label="Dashboard navigation">
  • Main content area must use <main>
  • Page headers must use correct heading hierarchy (h1h2h3, not skipping levels)
  • Data tables must have <caption> or aria-label, and use <th scope="col"> for headers

5. Interactive Component Audit

Check and fix these specific components:

  • Star rating input: must be keyboard navigable with arrow keys and announce the current value to screen readers
  • Notification bell dropdown: must use aria-haspopup, aria-expanded, and focus trap
  • Status badges: if color is the only differentiator, add screen-reader text (<span className="sr-only">Status: In Transit</span>)
  • File upload dropzone: must be keyboard operable and announce the dropped file name
  • Countdown timer: must use aria-live="off" (not polite) to avoid constant announcements

Acceptance Criteria

  • axe-core reports zero critical or serious violations on /dashboard, /shipments, and /login
  • Skip-to-content link is present and functional in the root layout
  • All forms have associated labels (no placeholder-only labels)
  • Validation error messages use role="alert"
  • All modals trap focus correctly
  • All data tables have <th scope="col"> headers
  • Star rating component is keyboard navigable with arrow keys
  • Heading hierarchy is correct on all audited pages (no heading level skipped)
  • Color contrast passes 4.5:1 for all body text (verify with Lighthouse accessibility audit ≥ 90)

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions