Implement WCAG 2.2 AA accessibility for both screens
epic-organization-selection-and-onboarding-ui-task-009 — Conduct a full WCAG 2.2 AA accessibility pass on OrgSelectionScreen and MultiOrgContextSwitcher. Requirements: all interactive elements have semantic labels and roles; touch targets meet 44×44dp minimum; color contrast ratios meet 4.5:1 for text and 3:1 for UI components; focus order is logical and visible; screen reader (TalkBack/VoiceOver) announces org names, active state, loading states, and error messages via live regions; switch-access traversal is correct. Fix all findings and document the accessibility semantic structure in code comments.
Acceptance Criteria
Technical Requirements
Execution Context
Tier 6 - 158 tasks
Can start after Tier 5 completes
Implementation Notes
Use Flutter's built-in Semantics widget as the primary tool — avoid third-party accessibility packages. Wrap composite org cards with MergeSemantics so TalkBack reads them as a single item (org name + active badge) rather than several fragments. Apply ExcludeSemantics to purely decorative elements (dividers, background shapes). For loading spinners, wrap with Semantics(liveRegion: true, label: 'Loading organizations') so VoiceOver/TalkBack announces state changes without user interaction.
Contrast ratios must be verified programmatically against the project's design token colors — use the WCAG 2.1 relative luminance formula or the accessibility_tools package in debug mode. Touch targets: prefer wrapping with a SizedBox(width: 48, height: 48) rather than increasing visual padding — use Semantics(explicitChildNodes: false) to keep the merged label. For the MultiOrgContextSwitcher confirmation dialog, ensure focus moves into the dialog on open and returns to the trigger element on close. Document each Semantics wrapper with a comment explaining the semantic role and label strategy.
This is a critical requirement per the workshop findings: all three organizations (NHF, Blindeforbundet, HLF) have users with motor, cognitive, and sensory disabilities, and screen reader support was explicitly requested.
Testing Requirements
Write widget tests using flutter_test that: (1) pump OrgSelectionScreen and assert Semantics tree contains expected labels for each org card using tester.getSemantics(); (2) verify touch target sizes by checking RenderBox constraints are ≥ 44×44; (3) simulate loading state and assert live region Semantics node fires with correct label; (4) simulate error state and assert error message appears in Semantics tree; (5) verify focus order by tabbing through all focusable elements and asserting sequence. Run Flutter accessibility checker (SemanticsController.ensureSemantics) in all widget tests. Manual testing required on real TalkBack (Android 12+) and VoiceOver (iOS 16+) devices before marking complete. Document manual test results in PR description.
OrgSelectionScreen and OrgContextSwitcher render partner-specific logos, colors, and text from dynamic data. Golden tests (pixel-comparison screenshots) will fail whenever branding assets are updated in the backend, causing CI failures that block unrelated PRs and eroding developer trust in the test suite.
Mitigation & Contingency
Mitigation: Use fixture-based golden tests with static mock Organization models containing embedded test assets rather than network-fetched assets. Separate branding asset acceptance tests into a dedicated CI job that only runs on branding-related PRs and is maintained by the design team.
Contingency: If golden test maintenance overhead becomes excessive, replace pixel-comparison goldens with semantic widget tests that assert widget tree structure and key property values, reserving golden tests for only the most stable, design-critical elements.
Several partner organizations (especially Blindeforbundet) have users who rely entirely on VoiceOver or TalkBack. Complex branded card layouts with overlaid logos, names, and selection states are notoriously difficult to make fully accessible; missing semantics or incorrect focus order could make the selection screen completely unusable for screen reader users before launch.
Mitigation & Contingency
Mitigation: Involve an accessibility specialist in the design review before any widget implementation begins. Use Flutter's Semantics widget with explicit label, hint, and button role on OrgCardWidget. Conduct manual screen reader testing on both iOS (VoiceOver) and Android (TalkBack) for every sprint that touches these screens, not just before release.
Contingency: If full WCAG compliance cannot be achieved within the sprint, implement a simplified text-list fallback mode that activates when the system detects an active screen reader, presenting orgs as plain accessible list tiles instead of the branded card layout.