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 (
h1 → h2 → h3, 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
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:
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):Focus management:
@radix-ui/react-dialogif not already — check Radix is installed)Color contrast:
Images:
<img>elements and<Image>components must have descriptivealttextalt=""3. Form Accessibility
Audit all forms in the application:
<input>must have an associated<label>(viahtmlFor/id— not just placeholder)aria-required="true"role="alert"oraria-live="polite"so screen readers announce themrole="group"witharia-labelledby4. Navigation Landmarks
<nav aria-label="Dashboard navigation"><main>h1→h2→h3, not skipping levels)<caption>oraria-label, and use<th scope="col">for headers5. Interactive Component Audit
Check and fix these specific components:
aria-haspopup,aria-expanded, and focus trap<span className="sr-only">Status: In Transit</span>)aria-live="off"(notpolite) to avoid constant announcementsAcceptance Criteria
/dashboard,/shipments, and/loginrole="alert"<th scope="col">headers