Skip to main content

Accessibility Audit

Accessibility Audit

Project: Drop — Fintech Payment App{{PROJECT_NAME}} Version: 0.1.0{{VERSION}} Date: 2026-02-23{{DATE}} Author: John (AI Director, ALAI){{AUTHOR}} Status: Draft | In Review | Approved Reviewers: Alem Bašić (CEO){{REVIEWERS}}

Document History

Version Date Author Changes
0.1 2026-02-23{{DATE}} John{{AUTHOR}} 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 AspirationalTarget for paymentcritical flows (sendcheckout, money, QR payment)forms)
EN 301 549 Applicable If serving EU productpublic sector
Section 508 No{{Yes/No}} NoIf US federal contract

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


2. Audit Methodology

2.1 Automated Testing

  • axe-core: NotIntegrated yet integrated — planned forin Storybook + CI (via @axe-core/playwright)
  • Lighthouse: NotAccessibility yetscore runtracked onin productionCI build — target(target:9595)
  • pa11y: NotRun yeton configuredfull page URLs in staging environment

2.2 Manual Testing

  • Code review of all page components in src/drop-app/src/app/
  • No keyboard-Keyboard-only navigation testingon performedall yetcritical user flows
  • No screenScreen reader testing performed(see yetmatrix in Section 6)
  • NoZoom test: 200% browser zoom testing performedno yetloss of content or functionality
  • Reflow test: 320px viewport width

2.3 User Testing

  • {{Yes — included users with disabilities in user testing | No — planned for Phasefuture}}: 2 before production launch.{{Notes}}

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{{Pass}} CustomAll drop-icons<img> have alt; decorative images use currentColoralt="" 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-onlyIcon buttons have aria-label — NOT fully implemented (e.g., notification bell, logout button)
  • Complex images (charts, diagrams) have N/Along in current versiondescriptions
  • CAPTCHAs have N/Aaudio alternative
  • SVG icons: lucidemeaningful icons arerole="img" inlinearia-label="...", SVG;decorative → aria-hiddenhidden="true" not consistently set

Issues:

  • A11Y-001 (High):TODO: DashboardRun notification bellaxe and logoutlist buttonsall use icon-only UI without aria-label. Screen reader users cannot identify these controls.
violations.


1.2 Time-based Media

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

TODO: Audit all video/audio content on the platform.


1.3 Adaptable

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

Issues:Checklist:

  • A11Y-002 (Medium): Transaction amountsTables use color<th> with scope attributes
  •  Heading hierarchy is logical (green/red)H1 as theH2 only differentiatorH3, forno sentskipped vslevels)
  • received.
  • NeedsLists use +<ul> / -<ol> prefix (alreadynot presentstyled in transactions page) and screen reader-accessible labels.<div>
  • A11Y-003 (Low): Form inputs on /login and /register lackhave autocomplete attributes for name, email, phone.phone, address

1.4 Distinguishable

Criterion Status Notes Issue Ref
1.4.1 Use of Color (A) Partial{{Pass/Fail}} TransactionColor amounts:not colorsole used but +/- prefix also present. Tab active state: color only — lacks additional indicator.differentiator A11Y-004
1.4.2 Audio Control (A) N/A{{Pass/Fail}} No auto-Auto-play audio has stop mechanism
1.4.3 Contrast Minimum (AA) Partial{{Pass/Fail}} See contrast table in Section 9. Muted gray (#9CA3AF) fails WCAG AA for small text.below A11Y-005
1.4.4 Resize Text (AA) Unknown{{Pass/Fail}} Not tested at 200% zoom — no content loss
1.4.5 Images of Text (AA) Pass{{Pass/Fail}} Real text used, not images
1.4.10 Reflow (AA) Unknown{{Pass/Fail}} Not tested at 320px viewportwidth — no horizontal scroll
1.4.11 Non-text Contrast (AA) Partial{{Pass/Fail}} InputUI borders (#E5E7EB on #F9FAFB) may be belowcomponents 3:1 ratio A11Y-006
1.4.12 Text Spacing (AA) Unknown{{Pass/Fail}} NotCustom testedspacing doesn't break layout
1.4.13 Content on Hover/Focus (AA) Pass{{Pass/Fail}} NoTooltips hover-onlycan contentbe hovered/dismissed

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{{Pass/Fail}} NotAll testedfunctionality — shadcn/ui uses Radix (keyboard accessible), but custom components need verificationkeyboard-operable
2.1.2 No Keyboard Trap (A) Partial{{Pass/Fail}} CookieConsentFocus modalcan usesalways Dialogbe (Radix)moved — focus trap should work. Custom scan state machine may trap focus.away A11Y-007
2.1.4 Character Key Shortcuts (A) Pass{{Pass/Fail}} No single-Single-key shortcuts implementedcan be disabled

Checklist:

  • All interactive elements reachable by Tab key — not verified
  • BottomNavAll itemsactions keyboard-accessibletriggerable by not verifiedEnter/Space
  • QRNo scankeyboard pagetraps states(except keyboard-navigableintentional: modal notfocus verifiedtrap with Escape exit)
  • Multi-stepCustom formswidgets (register,follow send)ARIA keyboard-operableAuthoring Practices 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.patterns

2.2 Enough Time

Criterion Status Notes
2.2.1 Timing Adjustable (A) Pass{{Pass/Fail}} NoSession automatictimeout sessionwarns timeoutswith inoption currentto version (auth is httpOnly cookie, 7-day lifetime)extend
2.2.2 Pause, Stop, Hide (A) Pass{{Pass/Fail}} No auto-Auto-updating content inhas currentpause versioncontrol

2.3 Seizures and Physical Reactions

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

2.4 Navigable

Criterion Status Notes
2.4.1 Bypass Blocks (A) Fail{{Pass/Fail}} No skip-Skip-to-content link implemented
2.4.2 Page Titled (A) Partial{{Pass/Fail}} RootUnique layoutdescriptive haspage "Drop" title. Individual pages do not set unique <title> tags.titles
2.4.3 Focus Order (A) Unknown{{Pass/Fail}} NotFocus testedorder matches reading order
2.4.4 Link Purpose (A) Partial{{Pass/Fail}} NavigationLink linkstext aredescriptive labeled.in Some icon-only buttons lack context.context
2.4.6 Headings and Labels (AA) Partial{{Pass/Fail}} HeadingDescriptive hierarchyheading notand consistentlylabel used across pagestext
2.4.7 Focus Visible (AA) Partial{{Pass/Fail}} shadcn/uiFocus inputs have focus:border-[#0B6E35] focus:ring-1. Custom buttons may lackindicator visible focuson ring.all elements

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{{Pass/Fail}} <html langlang="en"> attribute not verified in root layout. Should be lang="nb" (Norwegian Bokmål).set
3.1.2 Language of Parts (AA) Pass{{Pass/Fail}} Applang ison Norwegian-onlyforeign inlanguage Phase 1sections

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{{Pass/Fail}} Focus does not trigger unexpected navigationchange
3.2.2 On Input (A) Pass{{Pass/Fail}} ToggleInput switcheschange (notifications)doesn't updateauto-submit immediately — user expectation for togglesform
3.2.3 Consistent Navigation (AA) Pass{{Pass/Fail}} BottomNavNav consistent across all authenticated pages
3.2.4 Consistent Identification (AA) Pass{{Pass/Fail}} Same iconsfunction used= consistentlysame across pageslabel

3.3 Input Assistance

Criterion Status Notes
3.3.1 Error Identification (A) Partial{{Pass/Fail}} Errors shownidentified asin redtext, text.not Notjust all error messages include field identification.color
3.3.2 Labels or Instructions (A) Pass{{Pass/Fail}} FormAll fields have labels present on login and register pages
3.3.3 Error Suggestion (AA) Partial{{Pass/Fail}} Some errorError messages suggest correction (e.g., "Passord må inneholde minst 8 tegn")
3.3.4 Error Prevention (AA) Pass{{Pass/Fail}} SendDestructive moneyactions and QR payment showrequire 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{{Pass/Fail}} ReactValid generatesHTML, valid HTML. Nono duplicate IDs via React's virtual DOM.
4.1.2 Name, Role, Value (A) Partial{{Pass/Fail}} shadcn/uiAll UI components (Dialog,have Tabs)accessible usename correct+ ARIA. Custom components need audit.role
4.1.3 Status Messages (AA) Fail{{Pass/Fail}} NoStatus messages announced via 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 1514 Safari HIGH Untested{{Pass/Fail/Untested}}
VoiceOver iOS 1817 Safari HIGH Untested{{Pass/Fail/Untested}}
NVDA Windows 11 Chrome HIGH Untested{{Pass/Fail/Untested}}
NVDA Windows 11 Firefox MEDIUM Untested{{Pass/Fail/Untested}}
JAWS Windows 11 Chrome HIGH Untested{{Pass/Fail/Untested}}
TalkBack Android 14 Chrome MEDIUM Untested{{Pass/Fail/Untested}}

Tested user flows:

    1. User registration / login (BankID verification)
    2. Send money (remittance 4-step flow)
    3.  QR payment scan flow
    4.  Transaction historyMain navigation
    5. BottomNavForm navigationsubmission with validation errors
    6. SettingsData togglestable (push/email notifications)sorting, pagination, row actions
  •  Modal open/close/action
  •  Toast / notification announced

  • 8. Keyboard Navigation Map

    Context Key Action
    Global Tab Next focusable element
    Global Shift+Tab Previous focusable element
    Global EnterEscape ActivateClose button,modal, followdropdown, linktoast
    Global SpaceAlt+S ActivateSkip buttonto main content (custom shortcut)
    BottomNavDropdown TabArrow Down/Up NextNavigate nav itemoptions
    BottomNavDropdown EnterEnter/Space NavigateSelect to routeoption
    DialogTableArrow keysNavigate cells (if grid role)
    Modal Tab Cycle within modal (focus trapped)
    DialogDate picker EscapeArrow keys CloseNavigate dialogdays
    Tabs (Transactions filter) Arrow keys Switch tab (Radix behavior)
    Form multi-stepEnterSubmit / proceed to next step
    Toggle switchSpaceToggle on/off
    Select dropdownArrow Down/UpNavigate options
    Select dropdownEnterSelect option

    9. Color Contrast Verification Table

    Element Text Color Background Ratio AA Pass (4.5:1) AAA Pass (7:1)
    PrimaryBody text #1A1A1A#0F172A #FAFCF8#FFFFFF ~18.6:1{{X:1}} Yes{{Y/N}} Yes{{Y/N}}
    Secondary text #374151#FAFCF8~10.2:1YesYes
    Muted text#6B7280#FAFCF8~4.7:1YesNo
    Inactive nav#9CA3AF#334155 #FFFFFF ~2.9:1{{X:1}} No{{Y/N}} No{{Y/N}}
    Disabled text#94A3B8#FFFFFF{{X:1}}{{Y/N}}{{Y/N}}
    Primary button text #FFFFFF #0B6E35#0EA5E9 ~5.0:1{{X:1}} Yes{{Y/N}} No{{Y/N}}
    Link color #0B6E35#FAFCF8~5.0:1YesNo
    Success (amounts)#10B981#0284C7 #FFFFFF ~3.0:1{{X:1}} No (small text){{Y/N}} No{{Y/N}}
    Error text #EF4444 #FFFFFF ~3.9:1No (small text)No
    Error text (large)#EF4444{{X:1}} #FFFFFF{{Y/N}} ~3.9:1Yes (large text ≥18px)No{{Y/N}}
    Placeholder #6B7280#94A3B8 #F9FAFB#FFFFFF ~4.5:1{{X:1}} Borderline{{Y/N}} No{{Y/N}}

    CriticalTODO: failures:Measure all values using {{Colour Contrast Analyser | axe DevTools}}.

    • #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

    Tabshandlestablist/tab/tabpanel
    Pattern ARIA Used Correct? Notes
    Modal dialog (CookieConsent) role="dialog", viaaria-modal="true", Radixaria-labelledby Yes{{Yes/No}} Radix Dialog handles correctly
    BottomNav navigationNavigation role="navigation", — not verifiedaria-label Unknown{{Yes/No}} Should have aria-label="Navigasjon"
    Alert / error messagesAlert/toast role="alert" or NOT implementedaria-live="polite" No{{Yes/No}} Error messages need live region
    Tab panel (Transactions) Radixrole="tablist", Tabsrole="tab", — correct rolesrole="tabpanel" Yes{{Yes/No}} Radix
    Accordionaria-expanded, aria-controls{{Yes/No}}
    Custom scan statesselect Norole="listbox", ARIArole="option", rolesaria-selected No{{Yes/No}} Needs aria-live for state transitions
    Loading states No aria-busybusy="true", live region{{Yes/No}} NoSkeleton and loading text lack ARIA
    Toggle switches (settings)Unknown — needs reviewUnknownShould use role="switch" or aria-checked

    11. Remediation Priority & Timeline

    {{Open/In
    Issue WCAG Criterion Severity Priority Assigned To Target Date Status
    A11Y-001:{{Issue Icon buttons lack aria-labeldescription}} {{1.1.14.3}} High{{Critical/High/Medium/Low}} P1 Frontend dev{{NAME}} Pre-v1.0{{DATE}} Open
    A11Y-005: Muted text #9CA3AF fails contrast1.4.3HighP1Frontend devPre-v1.0Open
    A11Y-007: Keyboard access in multi-step flows2.1.1HighP1Frontend devPre-v1.0Open
    A11Y-011: Missing lang="nb" on html element3.1.1HighP1Frontend devImmediateOpen
    A11Y-013: Scan page states lack ARIA4.1.2HighP1Frontend devPre-v1.0Open
    A11Y-014: No aria-live for transaction results4.1.3HighP1Frontend devPre-v1.0Open
    A11Y-002: Color-only transaction indicators1.3.1MediumP2Frontend devPre-v1.0Partial (has +/- prefix)
    A11Y-004: BottomNav active state color-only1.4.1MediumP2Frontend devPre-v1.0Open
    A11Y-008: No skip-to-content link2.4.1MediumP2Frontend devPre-v1.0Open
    A11Y-009: No unique page titles2.4.2MediumP2Frontend devPre-v1.0Open
    A11Y-010: Focus visibility inconsistent2.4.7MediumP2Frontend devPre-v1.0Open
    A11Y-012: Error messages lack aria-describedby3.3.1MediumP2Frontend devPre-v1.0Open
    A11Y-003: Missing autocomplete attributes1.3.5LowP3Frontend devPost-v1.0Open
    A11Y-006: Input border contrast1.4.11LowP3Frontend devPost-v1.0OpenProgress/Fixed}}

    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)x}}
    @axe-core/playwright Automated E2E accessibility checks {{4.x (to be integrated)x}}
    Lighthouse Automated CI performance + a11y score Built-in Chrome
    pa11y Automated Staged URL scanning {{6.x (to be integrated)x}}
    Colour Contrast Analyser Manual Color contrast spot checks TPGi
    VoiceOverScreen (macOS/iOS)readers Manual ScreenSee readermatrix testingabove Built-in
    TalkBack (Android)ManualScreen reader testingBuilt-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