high priority medium complexity frontend pending frontend specialist Tier 6

Acceptance Criteria

All tappable list items have a minimum touch target size of 44x44dp as measured by Flutter's SemanticsNode bounding boxes
Every interactive element has a Semantics widget with a meaningful label that describes the action and content (e.g., 'Select activity type: Physical meeting, 30 minutes')
All text and icon elements meet WCAG 2.2 AA contrast ratio of at least 4.5:1 for normal text and 3:1 for large text using design token color values
VoiceOver (iOS) and TalkBack (Android) correctly announce list items, loading state, and error state without double-reading or missing content
Focus traversal order follows the visual top-to-bottom, left-to-right reading order with no focus traps
A live region Semantics widget announces 'Activity types loaded, N options available' when the list successfully populates
A live region Semantics widget announces 'Error loading activity types. Tap to retry.' when an error state is displayed
The screen passes Flutter accessibility inspector with zero accessibility warnings
ExcludeSemantics is applied to purely decorative icons that convey no additional information
MergeSemantics correctly groups label + subtitle pairs so screen readers announce them as a single unit
Focus is not lost or reset when the list re-renders due to cache refresh
All interactive elements have a tooltip or semantic hint describing the result of the tap action

Technical Requirements

frameworks
Flutter
Riverpod
data models
ActivityType
performance requirements
Semantics tree construction must not add more than 2ms to frame render time
Live region announcements must fire within 100ms of the triggering state change
security requirements
Semantics labels must not expose internal IDs or sensitive org metadata to accessibility APIs
ui components
Semantics widget with label, hint, and liveRegion properties
MergeSemantics for grouped label+subtitle items
ExcludeSemantics for decorative icons
SizedBox or ConstrainedBox enforcing 44x44dp minimum tap area
Design token color values for all foreground/background pairs
CircularProgressIndicator wrapped with Semantics(label: 'Loading activity types')

Execution Context

Execution Tier
Tier 6

Tier 6 - 158 tasks

Can start after Tier 5 completes

Implementation Notes

Use Semantics(liveRegion: true, label: '...') wrapped around the list container to announce load completion — do not wrap individual items. Wrap each ListTile or custom item widget with a Semantics parent that merges child semantics. For touch targets, prefer wrapping in an InkWell or GestureDetector inside a SizedBox(height: 44, width: double.infinity) rather than padding hacks, as SizedBox correctly expands the hit-test area. Use design token ColorTokens.onSurface and ColorTokens.surface pairs exclusively — never hardcode hex values.

Focus traversal is automatic in Flutter's default traversal policy; verify it is not broken by any custom FocusNode usage introduced in the parent wizard. Use FocusTraversalGroup if reordering is needed. Run flutter analyze and dart fix before marking complete.

Testing Requirements

Widget tests must verify that SemanticsNode labels match expected strings using tester.getSemantics(). Use flutter_test's SemanticsController to traverse the semantics tree and assert liveRegion announcements fire on state transition. Contrast ratios must be verified by a static design token audit (unit test asserting color pair luminance ratios). Manual test pass required on a physical iOS device with VoiceOver enabled and an Android device with TalkBack enabled.

Accessibility inspector run must produce zero errors.

Epic Risks (2)
medium impact medium prob scope

Metadata flag combination rules differ between organisations (e.g., Blindeforbundet honorarium thresholds, HLF mutual exclusion of km and transit). Encoding these as generic service-level validation may be insufficient, forcing organisation-specific branching inside the service that becomes unmaintainable as new organisations are onboarded.

Mitigation & Contingency

Mitigation: Model flag validation as a pure function that accepts an ActivityTypeMetadata object and an org configuration record, making org-specific rules data-driven rather than hardcoded. Establish the validation contract in the foundation epic so the service just delegates to the validator.

Contingency: Defer complex cross-flag validation to a lightweight edge function that can be updated without a mobile app release, accepting that initial validation in the mobile service layer is permissive and corrected server-side.

high impact low prob technical

Blindeforbundet users rely on VoiceOver and JAWS. If the selection screen is built with non-semantic widgets that fail accessibility audit late in the sprint, a significant rework of the widget tree may be required, blocking the registration wizard integration.

Mitigation & Contingency

Mitigation: Build the selection screen against the project's established accessibility design tokens and semantics wrapper conventions from the start. Run Flutter's semantic tree inspector and a manual VoiceOver pass before marking any widget task complete.

Contingency: Wrap all tappable items in the project's SemanticsWrapperWidget and schedule a dedicated accessibility review session with a screen reader user from Blindeforbundet before the epic is closed.