critical priority medium complexity testing pending testing specialist Tier 6

Acceptance Criteria

Every interactive element in all six map UI components (MapViewScreen, MapMarkerWidget, ViewToggleButton, MentorInfoPopup, MentorListFallback, MapFilterPanel) is reachable via VoiceOver swipe navigation on iOS and TalkBack linear navigation on Android
Every interactive element has a non-empty, descriptive accessibility label that describes its purpose (not just its visual appearance)
Focus order is logical and follows reading order — no focus jumps or cycles that confuse screen reader users
Colour contrast ratios meet WCAG 2.2 AA: ≥4.5:1 for normal text, ≥3:1 for large text and UI components — verified with a contrast analyser tool on screenshots
Availability state is communicated via both colour AND a text/icon indicator — colour alone is never the sole differentiator
MentorListFallback provides full feature parity with map view: filtering, viewing mentor details, and navigating to mentor profile are all possible without leaving the list
No content is hidden or inaccessible when VoiceOver or TalkBack is active — no elements with accessibilityElementsHidden or importantForAccessibility=no that should be visible
All findings are documented in a structured audit report with: component name, WCAG criterion, pass/fail, severity (critical/major/minor), and reproduction steps
Any audit failure of severity 'critical' or 'major' has a corresponding fix task created with the exact finding referenced
The audit report is reviewed and signed off by the product owner before the epic is marked complete

Technical Requirements

frameworks
Flutter
VoiceOver (iOS)
TalkBack (Android)
data models
PeerMentor
AvailabilityState
MapFilterState
performance requirements
Audit must be performed on real devices (iPhone and Android physical device), not simulators, for accurate screen reader behaviour
security requirements
Audit must be performed with anonymised/synthetic mentor data — no real user data on audit devices
ui components
MapViewScreen
MapMarkerWidget
ViewToggleButton
MentorInfoPopup
MentorListFallback
MapFilterPanel

Execution Context

Execution Tier
Tier 6

Tier 6 - 158 tasks

Can start after Tier 5 completes

Implementation Notes

Conduct the audit in two sessions: one on iOS with VoiceOver (tester must be familiar with VoiceOver swipe gestures), one on Android with TalkBack. For contrast ratio checks, take high-resolution screenshots of each component in both available and unavailable states and measure with the Colour Contrast Analyser desktop tool. The most common Flutter accessibility pitfalls to check: (1) GestureDetector without a Semantics wrapper, (2) Image widgets without semanticLabel, (3) AnimatedOpacity hiding content without excludeFromSemantics, (4) custom painted widgets with no semantics override. The list fallback parity check is the most critical item for Blindeforbundet users — verify that every action available on the map is reachable from the list without switching views.

Testing Requirements

Manual audit — no automated test runner. Use the WCAG 2.2 AA checklist as the audit framework, specifically success criteria: 1.1.1 (Non-text Content), 1.3.1 (Info and Relationships), 1.3.2 (Meaningful Sequence), 1.4.1 (Use of Colour), 1.4.3 (Contrast Minimum), 2.1.1 (Keyboard/focus navigability), 2.4.3 (Focus Order), 2.4.6 (Headings and Labels), 4.1.2 (Name, Role, Value). Supplement with Flutter Accessibility Scanner on Android. Capture screen recordings of VoiceOver and TalkBack sessions as evidence.

All findings logged in a shared audit spreadsheet with severity ratings.

Component
Mentor List Fallback View
ui low
Epic Risks (3)
high impact high prob technical

Flutter's map canvas (flutter_map) does not natively support semantic focus traversal for screen readers, meaning map markers may be entirely invisible to VoiceOver/TalkBack users. If the accessible list fallback is not treated as a first-class view, screen reader users will have no access to the feature.

Mitigation & Contingency

Mitigation: From sprint 1, treat mentor-list-fallback as a fully featured primary view, not an afterthought. Implement and test it in parallel with the map canvas. Make the view-toggle-button keyboard focusable and announced on every screen state. Conduct VoiceOver testing on device before submitting each PR touching UI components.

Contingency: If map canvas accessibility cannot be achieved for marker focus traversal, make the view-toggle-button the default focus target on screen load for VoiceOver users (detected via screen-reader-detection-service) so they are immediately directed to the list fallback without needing to discover the toggle.

medium impact medium prob technical

The mentor-info-popup must occupy no more than 40% of visible map area on small screens. On devices with screen heights under 667px (iPhone SE), overlapping with the filter panel or obscuring most of the map could severely degrade usability.

Mitigation & Contingency

Mitigation: Implement the popup as a bottom sheet capped at 40% of screen height with a ScrollView for overflow content. Test on iPhone SE (375x667pt) and the smallest commonly used Android form factor in the device lab. Define max-height as a percentage constant in location-privacy-config or design tokens.

Contingency: If the popup cannot fit all required fields within 40% height on smallest targets, truncate assigned contact count and certification badge to icons-only in the compact view, with a 'View Profile' button always visible at the bottom of the popup regardless of scroll position.

medium impact medium prob integration

Filter state must remain perfectly synchronised between the map view and the list fallback. If the filter panel emits state that is not consumed identically by both views, coordinators switching between views will see inconsistent mentor sets, eroding trust in the feature.

Mitigation & Contingency

Mitigation: Store active filter criteria in a single shared Riverpod provider owned by the map-view-screen and consumed by both map-marker-widget (via mentor-location-service) and mentor-list-fallback. Write integration tests that apply a filter, switch views, and assert identical mentor counts in both views.

Contingency: If filter sync proves brittle, simplify to a single filter state object passed explicitly as a constructor argument to both views on each rebuild, eliminating indirect state sharing.