Files
goodgo-platform/docs/audits/ACCESSIBILITY_AUDIT_QUICK_REFERENCE.md
Ho Ngoc Hai 59272e9321 chore(docs): consolidate 22 audit files from root into docs/audits/
Root directory had accumulated audit/exploration markdown files cluttering
the project root. Moved all audit-related files to docs/audits/ with a
README.md index, and updated cross-references in K6_LOAD_TESTING_GUIDE.md
and README_FRONTEND_DOCS.md.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-10 23:16:00 +07:00

8.6 KiB

GoodGo Platform Accessibility Audit - Quick Reference

Date: April 10, 2026 | Status: 70-75% WCAG 2.1 AA Compliant


📊 Key Metrics

Metric Count Status
Total Files Analyzed 90+
ARIA Attributes Found 75
Files Using ARIA 14
Critical Issues 2 🔴
Major Issues 3 🟡
Minor Issues 2 🟢

🔴 CRITICAL ISSUES (Must Fix)

1. Dialog Component Missing Accessibility

File: apps/web/components/ui/dialog.tsx Issues:

  • Missing role="dialog"
  • Missing aria-modal="true"
  • No focus trap
  • No escape key handling
  • Background not hidden from screen readers

Time to Fix: 2-3 hours | Priority: 1

Quick Fix Checklist:

  • Add role="dialog" to dialog container
  • Add aria-modal="true"
  • Implement escape key listener
  • Add aria-hidden="true" to backdrop
  • Test with NVDA screen reader

File: apps/web/components/listings/image-gallery.tsx:69-84 Issue: Thumbnail buttons lack aria-labels

Time to Fix: 15-30 minutes | Priority: 2

Quick Fix:

// Add this to each thumbnail button:
aria-label={`Select image ${index + 1}${img.caption ? ': ' + img.caption : ''}`}
aria-pressed={index === selectedIndex}

🟡 MAJOR ISSUES (Should Fix)

1. Admin Layout Header Missing Banner Role

File: apps/web/app/[locale]/(admin)/layout.tsx:134

Quick Fix:

// Change from:
<header className="sticky...">

// To:
<header role="banner" className="sticky...">

Time to Fix: 2 minutes | Priority: 3


2. Color Contrast Not Verified

Issue: CSS variables defined but contrast ratios not tested Impact: Potential WCAG 1.4.3 violation Time to Fix: 4-6 hours testing

Testing Checklist:

  • Extract CSS variable values from globals.css
  • Test with WebAIM Contrast Checker
  • Verify 4.5:1 for normal text (WCAG AA)
  • Verify 7:1 for AAA compliance
  • Test in both light and dark modes

3. Landing Page Search Input Missing Visible Label

File: apps/web/app/[locale]/(public)/page.tsx:87-92

Quick Fix:

<div className="flex flex-col gap-1">
  <label htmlFor="search-input" className="sr-only">
    {t('landing.searchPlaceholder')}
  </label>
  <Input
    id="search-input"
    placeholder={t('landing.searchPlaceholder')}
    value={searchQuery}
    onChange={(e) => setSearchQuery(e.target.value)}
  />
</div>

Time to Fix: 30 minutes | Priority: 4


🟢 MINOR ISSUES (Nice to Have)

1. Redundant aria-labels on Visible Text

File: apps/web/app/[locale]/(dashboard)/layout.tsx:125 Issue: Links have aria-label when text is already visible

Recommendation: Remove redundant aria-labels - visible text is better for accessibility


WHAT'S WORKING WELL

Authentication Forms

  • All inputs have visible labels with <Label htmlFor="id">
  • Error messages linked via aria-describedby
  • Invalid state marked with aria-invalid
  • Password toggle has proper aria-label
  • Example: apps/web/app/[locale]/(auth)/login/page.tsx
  • Properly implemented with focus visibility
  • Hidden by default, visible on focus
  • Links to id="main-content"
  • Example: apps/web/app/[locale]/layout.tsx:105-110

Navigation

  • All navs have aria-label
  • Mobile menu toggles have dynamic labels
  • Icons properly hidden with aria-hidden="true"
  • Examples: All layout files

Search & Filters

  • Filter section has role="search"
  • All selects have aria-label
  • Range inputs properly labeled
  • Example: apps/web/components/search/filter-bar.tsx
  • Previous/Next buttons have aria-labels
  • Good semantic structure
  • Example: apps/web/components/listings/image-gallery.tsx:47, 54

📋 TESTING CHECKLIST

Before Deployment

  • Fix dialog component accessibility
  • Add thumbnail button labels
  • Add banner role to admin header
  • Run Lighthouse accessibility audit (target: 90+)
  • Test with NVDA screen reader
  • Test keyboard navigation (Tab, Shift+Tab, Enter, Escape)
  • Verify color contrast ratios
  • Test theme switching (light/dark mode)

Screen Reader Testing (NVDA)

  • Login form: Can fill fields, hear error messages
  • Navigation: Can navigate menus, understand current page
  • Search: Can find and submit search form
  • Dialogs: Can open, interact, close with Escape key
  • Image gallery: Can select images, hear which is selected
  • Mobile menu: Can open/close, toggle working properly

Keyboard Navigation

  • Tab: Moves through all interactive elements in logical order
  • Shift+Tab: Moves backward through elements
  • Enter: Activates buttons/links/form submission
  • Space: Activates buttons, toggles checkboxes
  • Escape: Closes modals/menus
  • Arrow keys: Works in dropdowns/carousels

🎯 Priority Roadmap

Week 1 (40 hours)

  1. Fix Dialog Component (2-3 hrs)

    • Add role, aria-modal, focus trap, escape handling
    • Test with screen reader
  2. Add Thumbnail Labels (0.5 hrs)

    • Add aria-label to thumbnail buttons
    • Test
  3. Fix Admin Header (0.1 hrs)

    • Add role="banner"
  4. Verify Contrast (6-8 hrs)

    • Extract CSS variables
    • Test all combinations
    • Document findings
    • Adjust if needed
  5. Add Landing Page Label (0.5 hrs)

    • Add visible label to search input
  6. Browser Testing (8 hrs)

    • NVDA testing
    • Chrome/Firefox/Safari testing
    • Mobile testing

Week 2 (20 hours)

  1. Remove Redundant Labels (0.5 hrs)
  2. Additional Skip Links (2-3 hrs)
  3. Comprehensive Testing (8 hrs)
  4. Fix Any Found Issues (6 hrs)

📁 File Reference

Critical Files to Review/Fix

  • apps/web/components/ui/dialog.tsx - 🔴 REWRITE NEEDED
  • apps/web/components/listings/image-gallery.tsx - 🔴 MINOR FIX NEEDED
  • apps/web/app/[locale]/(admin)/layout.tsx - 🟡 ADD ROLE
  • apps/web/app/globals.css - 🟡 VERIFY COLORS (not audited)

Files with Good Accessibility

  • apps/web/app/[locale]/(public)/layout.tsx - EXCELLENT
  • apps/web/app/[locale]/(auth)/login/page.tsx - EXCELLENT
  • apps/web/app/[locale]/(auth)/register/page.tsx - EXCELLENT
  • apps/web/components/ui/button.tsx - GOOD
  • apps/web/components/ui/input.tsx - GOOD
  • apps/web/components/ui/label.tsx - GOOD
  • apps/web/components/ui/select.tsx - GOOD
  • apps/web/components/search/filter-bar.tsx - GOOD

🔍 Code Examples

Good ARIA Usage Example

// Good: Dynamic aria-label that updates based on state
<button
  aria-label={mobileMenuOpen ? t('nav.closeMenu') : t('nav.openMenu')}
  onClick={() => setMobileMenuOpen(!mobileMenuOpen)}
>
  {mobileMenuOpen ? <X /> : <Menu />}
</button>

Form Accessibility Example

// Good: Proper label association + error handling
<div className="space-y-2">
  <Label htmlFor="phone">{t('phone')}</Label>
  <Input
    id="phone"
    type="tel"
    aria-describedby={errors.phone ? 'phone-error' : undefined}
    aria-invalid={!!errors.phone}
    {...register('phone')}
  />
  {errors.phone && (
    <p id="phone-error" role="alert">{errors.phone.message}</p>
  )}
</div>

Search Form Example

// Good: Proper semantic role with labeled controls
<form role="search" aria-label={t('filters')}>
  <Select aria-label={t('allTransactions')}>
    {/* options */}
  </Select>
</form>

📞 Resources

Documentation

  • Full audit report: ACCESSIBILITY_AUDIT_2026-04-10.md
  • Detailed findings on 15 sections
  • File-by-file analysis
  • WCAG 2.1 compliance assessment

Testing Tools

Learning Resources


📝 Notes

Audit Scope: apps/web (Next.js 14 frontend) Files Analyzed: 90+ TSX/JSX files Time to Achieve AA Compliance: 4-6 days full-time Ongoing Maintenance: Add to CI/CD, developer training recommended

Next Steps:

  1. Review full audit report (1552 lines)
  2. Create Jira tickets for each issue
  3. Assign tasks to development team
  4. Schedule accessibility testing
  5. Plan developer training session