high priority low complexity frontend pending frontend specialist Tier 2

Acceptance Criteria

All text in ContactCardWidget meets WCAG 2.2 AA minimum contrast ratio: 4.5:1 for normal text (below 18pt/14pt bold), 3:1 for large text (18pt+ or 14pt+ bold)
All non-text UI components (role badge border, icon, divider) meet 3:1 contrast ratio against adjacent colors
The card's tappable hit area is at least 44x44 logical pixels (dp) — implemented via GestureDetector with minimum size or SizedBox padding, not just the visible card bounds
Every ContactCardWidget is wrapped with a Semantics widget that provides a descriptive label combining contact name, role, and relevant status — readable aloud by TalkBack and VoiceOver without ambiguity
Role badge background/foreground color pair is sourced from the design token contrast-safe palette and passes automated contrast check
No hardcoded color values remain — all colors reference design tokens
Widget renders correctly and passes contrast requirements in both light and dark mode
Running the widget in flutter_test with a semantics tree inspection confirms correct Semantics labels and no missing semantic annotations
Zero WCAG regressions introduced compared to the pre-task baseline audit

Technical Requirements

frameworks
Flutter
flutter_test
data models
Contact
UserRole
performance requirements
Semantics wrapping must not introduce measurable frame-time overhead (< 1ms per card)
Touch target expansion via ExcludeSemantics or GestureDetector must not affect scroll performance in lists with 100+ items
security requirements
Semantics labels must not expose sensitive PII beyond what is already visible on screen — do not include internal IDs or raw database fields in label strings
ui components
Semantics widget wrapper
GestureDetector or InkWell with minimum 44dp hit target
Design token color references (AppColors / ThemeData extension)
Role badge widget using contrast-safe token colors

Execution Context

Execution Tier
Tier 2

Tier 2 - 518 tasks

Can start after Tier 1 completes

Implementation Notes

Use the Flutter Semantics widget directly around the card's InkWell/GestureDetector. The semanticsLabel should follow the pattern: '{contactName}, {roleName}, {statusIfRelevant}' so screen readers announce a complete description in a single focus stop. For touch target enforcement, wrap the visible card with a SizedBox(width: double.infinity) and ensure the InkWell's minimum tap target is enforced via Theme.of(context).materialTapTargetSize or by explicitly padding the GestureDetector. For contrast validation, build a small utility function `double wcagContrastRatio(Color fg, Color bg)` using the WCAG relative luminance formula — call this in tests, not at runtime.

All colors must be pulled from the app's design token system (e.g., AppColors.roleAdminBadgeFg / AppColors.roleAdminBadgeBg); never hardcode hex values. Cross-check the role badge token pairs against the contrast-safe palette defined in the design token documentation before finalizing.

Testing Requirements

Write flutter_test widget tests that: (1) assert the Semantics node for a ContactCardWidget contains the expected label string for a given contact fixture; (2) verify the rendered widget's hit-test area is >= 44x44 dp using tester.getSize(); (3) programmatically compute contrast ratio for each color pair used in the card (background/text, badge background/badge text) and assert >= 4.5:1 for normal text and >= 3:1 for large/UI elements — use a helper function that accepts two Color values and returns the WCAG ratio. Run tests in both light and dark ThemeData contexts. No integration or e2e tests required for this task.

Component
Contact Card Widget
ui low
Epic Risks (2)
medium impact medium prob technical

Design token color values used in role badges, certification status indicators, and availability chips may not meet the WCAG 2.2 AA contrast ratio of 4.5:1 when rendered against card backgrounds, requiring rework after accessibility review and potentially blocking acceptance sign-off.

Mitigation & Contingency

Mitigation: Run the contrast-ratio-validator on every new token combination during widget development. Enforce the CI accessibility lint runner on all PRs touching visualization components, and validate against the contrast-safe-color-palette before finalizing card designs.

Contingency: If contrast failures are found late, adjust token values in the design token theme centrally — since all widgets consume design tokens rather than hardcoded colors, all affected widgets will be corrected by a single token update without per-widget changes.

low impact medium prob dependency

The ContactViewSwitcher is required for Barnekreftforeningen but must not appear for other organizations. If the organization labels provider does not yet expose a reliable feature flag for this widget, it may render universally or be conditionally hidden in an inconsistent way, breaking the role-specific layout contract.

Mitigation & Contingency

Mitigation: Implement view switcher visibility as a constructor parameter on ContactListScreen injected from a provider, defaulting to hidden. Document the integration point for the org labels provider so the flag can be wired without changing the widget's API.

Contingency: If org labels integration is delayed beyond this epic, use a feature flag constant keyed to the Barnekreftforeningen organization ID as a temporary gate, with a tracked issue to replace it with the runtime labels provider before general release.