Implement WCAG 2.2 AA accessibility layer
epic-benefit-calculator-ui-and-share-task-011 — Apply full WCAG 2.2 AA compliance across all five components: add live region announcements on calculation completion so VoiceOver/TalkBack reads new metric values automatically, ensure all interactive controls meet 44x44dp touch target minimums, verify contrast ratios on metric values and card backgrounds, add merge semantics on BenefitMetricTile for cleaner VoiceOver grouping, and validate focus order on BenefitCalculatorScreen with both VoiceOver and TalkBack.
Acceptance Criteria
Technical Requirements
Execution Context
Tier 5 - 253 tasks
Can start after Tier 4 completes
Implementation Notes
Wrap BenefitResultsCard's container with Semantics(liveRegion: true, child: ...) — do NOT place liveRegion on a widget that rebuilds constantly as it will spam announcements. Use a ValueNotifier or BlocListener to trigger a one-time Semantics.announce() call after calculation completion as a belt-and-suspenders approach alongside the liveRegion. For touch targets, prefer wrapping with a SizedBox(width: 44, height: 44) constraint rather than GestureDetector padding — this keeps the visual footprint clean. Contrast checks: pull background and text colors from AppColors design tokens and write a unit test that asserts the computed WCAG contrast ratio ≥ 4.5.
For haptics, inject AccessibilityPreferencesRepository into the BLoC and gate HapticFeedback.lightImpact() calls behind the hapticFeedbackEnabled flag. The Norwegian accessibility regulation (WCAG 2.2 AA) is legally mandated for apps serving users with disabilities — treat this task as non-negotiable.
Testing Requirements
Widget tests must verify: (1) SemanticsNode for BenefitResultsCard has liveRegion set to true; (2) each BenefitMetricTile's SemanticsNode merges descendant labels and values into a single node; (3) all interactive SemanticsNodes have a minimum rect size of 44x44dp using tester.getSemantics(); (4) focus order follows the expected sequence using FocusTraversalGroup verification. Manual testing required on a physical iPhone (VoiceOver) and Android device (TalkBack) — document results in a test checklist. Use flutter_test SemanticsController for automated assertions. Contrast ratios validated statically against design token values in a dedicated unit test helper.
The RepaintBoundary PNG capture approach for sharing the results card may produce blurry or oversized images on high-DPI devices, or may silently fail on certain Android OEM configurations that restrict off-screen rendering. A failed share would break one of the core use cases (recruitment tool).
Mitigation & Contingency
Mitigation: Implement the capture using the established screenshot-capture-utility pattern already present in the Wrapped summary feature (component 542-screenshot-capture-utility). Test on a range of iOS and Android devices including Samsung and Huawei OEM builds during development. Set explicit pixel ratio (3.0) when calling toImage() to guarantee resolution.
Contingency: If image capture fails on a platform, the BenefitShareService falls back to sharing the plain-text summary only, with a user-facing message explaining the image could not be generated. This ensures the share flow never fully blocks.
Implementing full WCAG 2.2 AA compliance for the results card and metric tiles — including live regions, focus management, and semantic labels that read naturally in Norwegian — requires deep familiarity with Flutter semantics APIs. Gaps may only surface during screen reader testing on physical devices, late in the sprint.
Mitigation & Contingency
Mitigation: Use the existing semantics-wrapper-widget (606) and live-region-announcer (608) components from the accessibility feature rather than implementing custom semantics. Assign screen reader testing on a physical iPhone with VoiceOver as a mandatory acceptance gate, not an afterthought. Write widget tests using Flutter's AccessibilityGuideline matchers early in development.
Contingency: If screen reader issues are found late, the pure semantic markup approach (no Canvas numbers, all Semantics wrappers) limits the blast radius to label text corrections. Escalate to the accessibility feature team for a pairing session to resolve complex focus management issues.
The BenefitResultsCard must match the Wrapped design language used in the annual summary feature. If design tokens or widget patterns are inconsistent between the two features, the results card will look out of place and undermine the intended emotional impact for sharing.
Mitigation & Contingency
Mitigation: Review the existing Wrapped summary screen (529-wrapped-summary-screen) and stat card widget (530-stat-card-widget) implementations before building the results card. Reuse design tokens from the existing design-token-theme (200) system. Involve the designer in a review of the results card mock-up against the Wrapped language before implementation begins.
Contingency: If design parity issues are discovered post-implementation, isolate visual adjustments to the BenefitResultsCard widget. The feature's business logic and accessibility compliance are unaffected by visual polish changes.