Multi-Select WCAG 2.2 AA accessibility compliance
epic-bulk-and-proxy-registration-mentor-selection-task-011 — Apply WCAG 2.2 AA compliance to the Peer Mentor Multi-Select List: checkbox touch targets must meet the 44×44 dp minimum, correct checkbox semantics via Flutter Semantics with checked/unchecked state exposed to screen readers, live region announcement when selection count changes, contrast ratio validation on the count badge and select-all control, and full keyboard/switch-access navigation order verification. Critical for Blindeforbundet screen reader dependency.
Acceptance Criteria
Technical Requirements
Execution Context
Tier 7 - 84 tasks
Can start after Tier 6 completes
Implementation Notes
Touch target: wrap the entire MentorListItem row in a Material widget with InkWell (provides 48dp ripple by default) or explicitly set constraints via ConstrainedBox(constraints: BoxConstraints(minHeight: 44, minWidth: 44)). For checkbox semantics, use Semantics(checked: isSelected, label: mentorName, onTap: ..., child: ...) and set excludeSemantics: true on the inner Checkbox widget to prevent duplicate announcements. For the tri-state select-all, Flutter's Checkbox widget has a tristate: true property — use it with value: null for indeterminate, true for all selected, false for none. The Semantics wrapper should pass value: null correctly.
For contrast: reference design token colors (AppColors.textPrimary on AppColors.surface, etc.) and verify against WCAG formula at build time or in a dedicated test. For focus order: Flutter respects widget tree order for traversal by default; ensure the widget hierarchy is search bar → select-all → ListView → continue button. Use FocusTraversalGroup if manual ordering is needed. Avoid MergeSemantics on rows that contain multiple interactive elements (checkbox + row tap) — use a single Semantics node for the whole row instead.
Testing Requirements
Accessibility widget tests using flutter_test SemanticsController: (1) Assert every MentorListItem has a Semantics node with isChecked/isNotChecked set correctly. (2) Assert SelectAllToggle has a Semantics node with hasCheckedState and correct value. (3) Assert SelectedCountBadge Semantics node has liveRegion: true. (4) Assert search field Semantics node has label 'Search peer mentors'.
(5) Verify focus order by traversing Semantics tree nodes and asserting correct sequence. Manual testing on-device: VoiceOver (iOS) and TalkBack (Android) end-to-end walkthrough — screen reader must announce every state change without requiring sighted assistance. Contrast verification: automated test asserting design token color values meet 4.5:1 ratio (use a helper that computes relative luminance from hex values).
NHF coordinators may manage dozens of peer mentors across multiple chapters. If the multi-select list renders all contacts in a single unsorted ListView, performance degrades with 50+ items, and coordinators cannot efficiently locate a specific mentor, increasing the probability of selection errors and wrong-person proxy registrations.
Mitigation & Contingency
Mitigation: Use a SliverList with itemExtent for fixed-height rows to enable O(1) scroll position calculation. Implement the search filter using a debounce utility operating on an in-memory list (no extra API calls). Sort the contact list alphabetically by default. Add chapter-filter chips above the list for NHF's multi-chapter coordinators.
Contingency: If performance issues arise in testing with real data sets, introduce pagination with a 'load more' trigger at the bottom of the list and cache rendered rows using Flutter's AutomaticKeepAliveClientMixin.
NHF has a complex 12-national-association / 9-region / 1,400-chapter hierarchy. It is ambiguous whether a coordinator can proxy-register for peer mentors outside their immediately assigned chapter. If the contact list is not correctly scoped by RLS, coordinators might see — and register on behalf of — peer mentors they do not manage, creating fraudulent activity records that skew Bufdir statistics.
Mitigation & Contingency
Mitigation: The Proxy Contact List Provider must query only peer mentors linked to the coordinator's own chapter scope via RLS. Add an explicit Supabase query test asserting that a coordinator from chapter A cannot retrieve peer mentors from chapter B. Display each mentor's chapter affiliation in the list row so coordinators can visually verify scope.
Contingency: If RLS scope is found to be too permissive in testing, apply a server-side coordinator_id filter as a secondary guard on the query. Block the feature release until the scope test passes consistently.