Add WCAG 2.2 AA semantics to Assignment Editor
epic-multi-chapter-membership-handling-ui-task-010 — Annotate ChapterAssignmentEditor with full Semantics coverage: label the search field, mark each chapter list item with combined chapter and status label, add Tooltip and Semantics to End Affiliation buttons, and ensure the maximum-enforcement banner is announced as a live region alert. Verify touch targets are minimum 44×44 logical pixels. Run Flutter accessibility inspector and fix any warnings.
Acceptance Criteria
Technical Requirements
Execution Context
Tier 4 - 323 tasks
Can start after Tier 3 completes
Implementation Notes
Use MergeSemantics sparingly — prefer setting label/hint directly on the outermost GestureDetector or InkWell. For the live region banner, wrap the AnimatedSwitcher or Visibility widget with Semantics(liveRegion: true, label: bannerText) and rebuild the node when the banner appears so TalkBack/VoiceOver announces it. For 44×44 touch targets, prefer setting minimumSize on ButtonStyle or wrapping with SizedBox(width: 44, height: 44) rather than adding padding, to avoid layout shifts. Use the debugSemantics flag during development: flutter run --dart-define=SEMANTICS_DEBUG=true.
Check the Flutter accessibility inspector in DevTools (Semantics tab) after each annotation pass. Be careful not to double-announce interactive state — if BLoC already provides status text in the list item label, do not also set value: on the Semantics node.
Testing Requirements
Widget tests using flutter_test and SemanticsChecker.check() must pass with zero warnings for the ChapterAssignmentEditor widget tree. Write a test that pumps ChapterAssignmentEditor, calls tester.ensureSemantics(), and asserts: (1) a node with label containing 'Search chapters' exists, (2) each chapter item node merges name + status, (3) End Affiliation button nodes have non-empty hint, (4) the max-chapters banner node has liveRegion set. Use tester.tap() on each interactive element and assert no exception is thrown for touch target size. Run flutter test --coverage and ensure the semantics annotation code paths reach >90% coverage.
The Duplicate Activity Warning Dialog must announce itself to VoiceOver and TalkBack immediately on appearance. Flutter's default modal semantics do not guarantee focus shift to the dialog on all platform versions, risking silent appearance for screen reader users — a WCAG 2.2 failure.
Mitigation & Contingency
Mitigation: Wrap the dialog content in a Semantics node with liveRegion: true and explicitly request focus via FocusScope.of(context).requestFocus() on the dialog's primary action button in the post-frame callback. Test on physical iOS (VoiceOver) and Android (TalkBack) devices, not only simulators.
Contingency: If automatic focus fails on a specific platform version, add a platform-specific fallback using SemanticsService.announce() to force a live region announcement of the dialog's headline text.
The Chapter Membership Cubit tracks pending changes before commit to support the two-step add/confirm flow. If the user navigates away mid-edit or the app is backgrounded, uncommitted pending state could be replayed incorrectly on return, causing phantom affiliation additions or removals.
Mitigation & Contingency
Mitigation: Design the Cubit to hold pending changes only in transient in-memory state with no persistence. On any navigation-away event, emit a reset state that discards pending changes. Prevent accidental navigation during an active edit by showing a discard-changes confirmation dialog.
Contingency: If state desync is reported in production, add an explicit state reconciliation step in the Cubit's onResume handler that re-fetches the authoritative affiliation list from the repository and resets all pending state before re-rendering.
The Chapter Assignment Editor's searchable chapter list must load quickly. If the organisation has hundreds of chapters (NHF has 1,400 local chapters) and the full list is fetched on dialog open, the editor will be slow to display and the search will be sluggish.
Mitigation & Contingency
Mitigation: Scope the chapter list to only chapters within the coordinator's administrative scope (not all 1,400), leveraging the existing hierarchy access scope service. Implement server-side search with a minimum 2-character threshold and debounce to avoid excessive Supabase queries.
Contingency: If the scoped list is still too large, add local caching of the chapter list with a 15-minute TTL and an explicit refresh button, ensuring the editor is always responsive even on poor network conditions.