Skip to main content

Accessibility Audit

Accessibility Audit

Project: Drop — Fintech Payment App Version: 0.1.0 Date: 2026-02-23 Author: John (AI Director, ALAI) Status: Draft Reviewers: Alem Bašić (CEO)

Document History

Version Date Author Changes
0.1 2026-02-23 John Initial draft — code-review based (no automated tools run yet)

1. Compliance Target

Standard Level Notes
WCAG 2.1 AA Minimum required
WCAG 2.1 AAA Aspirational for payment flows (send money, QR payment)
EN 301 549 Applicable EU product
Section 508 No No US federal contract

Audit date: 2026-02-23 (initial code review — automated testing TBD) Auditor: John (AI Director) Next scheduled audit: Before v1.0 production release


2. Audit Methodology

2.1 Automated Testing

  • axe-core: Not yet integrated — planned for Storybook + CI via @axe-core/playwright
  • Lighthouse: Not yet run on production build — target ≥ 95
  • pa11y: Not yet configured

2.2 Manual Testing

  • Code review of all page components in src/drop-app/src/app/
  • No keyboard-only navigation testing performed yet
  • No screen reader testing performed yet
  • No 200% zoom testing performed yet

2.3 User Testing

  • No — planned for Phase 2 before production launch.

Action: Run automated accessibility tools before v1.0 release. This document reflects code-review findings only.


3. Perceivable

1.1 Text Alternatives

Criterion Status Notes Issue Ref
1.1.1 Non-text Content (A) Partial Custom drop-icons use currentColor but lack aria-label / aria-hidden in several places. Lucide icons lack labels in some interactive contexts. A11Y-001

Checklist:

  • All <img> elements have descriptive alt text or alt=""
  • Icon-only buttons have aria-labelNOT fully implemented (e.g., notification bell, logout button)
  • Complex images (charts, diagrams) — N/A in current version
  • CAPTCHAs — N/A
  • SVG icons: lucide icons are inline SVG; aria-hidden not consistently set

Issues:

  • A11Y-001 (High): Dashboard notification bell and logout buttons use icon-only UI without aria-label. Screen reader users cannot identify these controls.

1.2 Time-based Media

Criterion Status Notes Issue Ref
1.2.1 Audio-only / Video-only (A) N/A No audio or video content in app
1.2.2 Captions (A) N/A No video content
1.2.3 Audio Description (A) N/A No video content
1.2.4 Captions Live (AA) N/A No live media
1.2.5 Audio Description Prerecorded (AA) N/A No video content

1.3 Adaptable

Criterion Status Notes Issue Ref
1.3.1 Info and Relationships (A) Partial Shadcn/ui components use semantic HTML. Transaction amounts use color only (red/green) without non-color indicator. A11Y-002
1.3.2 Meaningful Sequence (A) Pass DOM order matches visual order for all pages
1.3.3 Sensory Characteristics (A) Pass No "click the red button" instructions
1.3.4 Orientation (AA) Pass No locked orientation
1.3.5 Identify Input Purpose (AA) Partial Login/register inputs should use autocomplete attributes (email, given-name, etc.) A11Y-003

Issues:

  • A11Y-002 (Medium): Transaction amounts use color (green/red) as the only differentiator for sent vs received. Needs + / - prefix (already present in transactions page) and screen reader-accessible labels.
  • A11Y-003 (Low): Form inputs on /login and /register lack autocomplete attributes for name, email, phone.

1.4 Distinguishable

Criterion Status Notes Issue Ref
1.4.1 Use of Color (A) Partial Transaction amounts: color used but +/- prefix also present. Tab active state: color only — lacks additional indicator. A11Y-004
1.4.2 Audio Control (A) N/A No auto-play audio
1.4.3 Contrast Minimum (AA) Partial See contrast table in Section 9. Muted gray (#9CA3AF) fails WCAG AA for small text. A11Y-005
1.4.4 Resize Text (AA) Unknown Not tested at 200% zoom
1.4.5 Images of Text (AA) Pass Real text used, not images
1.4.10 Reflow (AA) Unknown Not tested at 320px viewport
1.4.11 Non-text Contrast (AA) Partial Input borders (#E5E7EB on #F9FAFB) may be below 3:1 ratio A11Y-006
1.4.12 Text Spacing (AA) Unknown Not tested
1.4.13 Content on Hover/Focus (AA) Pass No hover-only content

Issues:

  • A11Y-004 (Medium): BottomNav active tab indicator uses color only. Needs additional indicator (bold, underline, or icon change).
  • A11Y-005 (High): Muted text color #9CA3AF on white (#FFFFFF) = ~2.9:1 contrast ratio — fails WCAG AA 4.5:1. Used for timestamps, hints, inactive nav labels.
  • A11Y-006 (Medium): Input border color #E5E7EB on background #F9FAFB may not meet 3:1 for non-text contrast.

4. Operable

2.1 Keyboard Accessible

Criterion Status Notes Issue Ref
2.1.1 Keyboard (A) Unknown Not tested — shadcn/ui uses Radix (keyboard accessible), but custom components need verification
2.1.2 No Keyboard Trap (A) Partial CookieConsent modal uses Dialog (Radix) — focus trap should work. Custom scan state machine may trap focus. A11Y-007
2.1.4 Character Key Shortcuts (A) Pass No single-key shortcuts implemented

Checklist:

  • All interactive elements reachable by Tab key — not verified
  • BottomNav items keyboard-accessible — not verified
  • QR scan page states keyboard-navigable — not verified
  • Multi-step forms (register, send) keyboard-operable — not verified

Issues:

  • A11Y-007 (High): Multi-step flows (/register, /send, /scan) use state machines that may not be keyboard-accessible. Screen transitions between steps need verification.

2.2 Enough Time

Criterion Status Notes
2.2.1 Timing Adjustable (A) Pass No automatic session timeouts in current version (auth is httpOnly cookie, 7-day lifetime)
2.2.2 Pause, Stop, Hide (A) Pass No auto-updating content in current version

2.3 Seizures and Physical Reactions

Criterion Status Notes
2.3.1 Three Flashes (A) Pass No content flashes >3 times/sec. animate-pulse on scan page is slow (not flashing).

2.4 Navigable

Criterion Status Notes
2.4.1 Bypass Blocks (A) Fail No skip-to-content link implemented
2.4.2 Page Titled (A) Partial Root layout has "Drop" title. Individual pages do not set unique <title> tags.
2.4.3 Focus Order (A) Unknown Not tested
2.4.4 Link Purpose (A) Partial Navigation links are labeled. Some icon-only buttons lack context.
2.4.6 Headings and Labels (AA) Partial Heading hierarchy not consistently used across pages
2.4.7 Focus Visible (AA) Partial shadcn/ui inputs have focus:border-[#0B6E35] focus:ring-1. Custom buttons may lack visible focus ring.

Issues:

  • A11Y-008 (Medium): No skip-to-content link. Keyboard users must Tab through BottomNav on every page.
  • A11Y-009 (Medium): Pages lack unique <title> metadata. All pages inherit root "Drop" title.
  • A11Y-010 (Medium): Custom buttons and interactive elements may lack visible focus indicators in some contexts.

5. Understandable

3.1 Readable

Criterion Status Notes
3.1.1 Language of Page (A) Fail <html lang> attribute not verified in root layout. Should be lang="nb" (Norwegian Bokmål).
3.1.2 Language of Parts (AA) Pass App is Norwegian-only in Phase 1

Issues:

  • A11Y-011 (High): Root layout <html> element may not have correct lang="nb" attribute set. Must be verified.

3.2 Predictable

Criterion Status Notes
3.2.1 On Focus (A) Pass Focus does not trigger unexpected navigation
3.2.2 On Input (A) Pass Toggle switches (notifications) update immediately — user expectation for toggles
3.2.3 Consistent Navigation (AA) Pass BottomNav consistent across all authenticated pages
3.2.4 Consistent Identification (AA) Pass Same icons used consistently across pages

3.3 Input Assistance

Criterion Status Notes
3.3.1 Error Identification (A) Partial Errors shown as red text. Not all error messages include field identification.
3.3.2 Labels or Instructions (A) Pass Form labels present on login and register pages
3.3.3 Error Suggestion (AA) Partial Some error messages suggest correction (e.g., "Passord må inneholde minst 8 tegn")
3.3.4 Error Prevention (AA) Pass Send money and QR payment show confirmation step before transaction

Issues:

  • A11Y-012 (Medium): Error messages use color red only in some cases. Need to verify aria-live or aria-describedby on error messages.

6. Robust

Criterion Status Notes
4.1.1 Parsing (A) Pass React generates valid HTML. No duplicate IDs via React's virtual DOM.
4.1.2 Name, Role, Value (A) Partial shadcn/ui components (Dialog, Tabs) use correct ARIA. Custom components need audit.
4.1.3 Status Messages (AA) Fail No ARIA live regions implemented for transaction success/error messages.

Issues:

  • A11Y-013 (High): Custom scan page states (scanning, payment, paying, success) lack ARIA roles and announcements.
  • A11Y-014 (High): Transaction success/error messages not announced via aria-live regions. Screen reader users won't hear payment confirmations.

7. Screen Reader Testing Matrix

Screen Reader OS Browser Priority Status Tester Date
VoiceOver macOS 15 Safari HIGH Untested
VoiceOver iOS 18 Safari HIGH Untested
NVDA Windows 11 Chrome HIGH Untested
NVDA Windows 11 Firefox MEDIUM Untested
JAWS Windows 11 Chrome HIGH Untested
TalkBack Android 14 Chrome MEDIUM Untested

Tested user flows:

  • User registration / login (BankID verification)
  • Send money (remittance 4-step flow)
  • QR payment scan flow
  • Transaction history navigation
  • BottomNav navigation
  • Settings toggles (push/email notifications)

8. Keyboard Navigation Map

Context Key Action
Global Tab Next focusable element
Global Shift+Tab Previous focusable element
Global Enter Activate button, follow link
Global Space Activate button
BottomNav Tab Next nav item
BottomNav Enter Navigate to route
Dialog Tab Cycle within modal (focus trapped)
Dialog Escape Close dialog
Tabs (Transactions filter) Arrow keys Switch tab (Radix behavior)
Form multi-step Enter Submit / proceed to next step
Toggle switch Space Toggle on/off
Select dropdown Arrow Down/Up Navigate options
Select dropdown Enter Select option

9. Color Contrast Verification Table

Element Text Color Background Ratio AA Pass (4.5:1) AAA Pass (7:1)
Primary text #1A1A1A #FAFCF8 ~18.6:1 Yes Yes
Secondary text #374151 #FAFCF8 ~10.2:1 Yes Yes
Muted text #6B7280 #FAFCF8 ~4.7:1 Yes No
Inactive nav #9CA3AF #FFFFFF ~2.9:1 No No
Primary button text #FFFFFF #0B6E35 ~5.0:1 Yes No
Link color #0B6E35 #FAFCF8 ~5.0:1 Yes No
Success (amounts) #10B981 #FFFFFF ~3.0:1 No (small text) No
Error text #EF4444 #FFFFFF ~3.9:1 No (small text) No
Error text (large) #EF4444 #FFFFFF ~3.9:1 Yes (large text ≥18px) No
Placeholder #6B7280 #F9FAFB ~4.5:1 Borderline No

Critical failures:

  • #9CA3AF on white: 2.9:1 — fails AA. Used for inactive nav labels and muted hints.
  • #10B981 on white: 3.0:1 — fails AA for small text. Used for positive transaction amounts.
  • #EF4444 on white: 3.9:1 — fails AA for small text (14px). Used for error messages and negative amounts.

10. ARIA Usage Audit

Pattern ARIA Used Correct? Notes
Modal dialog (CookieConsent) role="dialog" via Radix Yes Radix Dialog handles correctly
BottomNav navigation role="navigation" — not verified Unknown Should have aria-label="Navigasjon"
Alert / error messages role="alert" — NOT implemented No Error messages need live region
Tab panel (Transactions) Radix Tabs — correct roles Yes Radix Tabs handles tablist/tab/tabpanel
Custom scan states No ARIA roles No Needs aria-live for state transitions
Loading states No aria-busy No Skeleton and loading text lack ARIA
Toggle switches (settings) Unknown — needs review Unknown Should use role="switch" or aria-checked

11. Remediation Priority & Timeline

Issue WCAG Criterion Severity Priority Assigned To Target Date Status
A11Y-001: Icon buttons lack aria-label 1.1.1 High P1 Frontend dev Pre-v1.0 Open
A11Y-005: Muted text #9CA3AF fails contrast 1.4.3 High P1 Frontend dev Pre-v1.0 Open
A11Y-007: Keyboard access in multi-step flows 2.1.1 High P1 Frontend dev Pre-v1.0 Open
A11Y-011: Missing lang="nb" on html element 3.1.1 High P1 Frontend dev Immediate Open
A11Y-013: Scan page states lack ARIA 4.1.2 High P1 Frontend dev Pre-v1.0 Open
A11Y-014: No aria-live for transaction results 4.1.3 High P1 Frontend dev Pre-v1.0 Open
A11Y-002: Color-only transaction indicators 1.3.1 Medium P2 Frontend dev Pre-v1.0 Partial (has +/- prefix)
A11Y-004: BottomNav active state color-only 1.4.1 Medium P2 Frontend dev Pre-v1.0 Open
A11Y-008: No skip-to-content link 2.4.1 Medium P2 Frontend dev Pre-v1.0 Open
A11Y-009: No unique page titles 2.4.2 Medium P2 Frontend dev Pre-v1.0 Open
A11Y-010: Focus visibility inconsistent 2.4.7 Medium P2 Frontend dev Pre-v1.0 Open
A11Y-012: Error messages lack aria-describedby 3.3.1 Medium P2 Frontend dev Pre-v1.0 Open
A11Y-003: Missing autocomplete attributes 1.3.5 Low P3 Frontend dev Post-v1.0 Open
A11Y-006: Input border contrast 1.4.11 Low P3 Frontend dev Post-v1.0 Open

Severity definitions:

  • Critical: Blocks users with disabilities from core functionality
  • High: Significant barrier, workaround exists
  • Medium: Inconvenience, does not block task completion
  • Low: Minor enhancement opportunity

12. Testing Tools

Tool Type Usage Version
axe-core Automated CI integration + Storybook 4.x (to be integrated)
@axe-core/playwright Automated E2E accessibility checks 4.x (to be integrated)
Lighthouse Automated CI performance + a11y score Built-in Chrome
pa11y Automated Staged URL scanning 6.x (to be integrated)
Colour Contrast Analyser Manual Color contrast spot checks TPGi
VoiceOver (macOS/iOS) Manual Screen reader testing Built-in
TalkBack (Android) Manual Screen reader testing Built-in
Accessibility Insights Manual Guided manual testing Microsoft

Approval

Role Name Date Signature
Author John (AI Director) 2026-02-23
Accessibility Lead
QA Lead
Product Owner