high priority low complexity testing pending testing specialist Tier 7

Acceptance Criteria

All interactive elements in ExpenseTypePickerWidget have touch targets of at least 44×44 dp as measured by flutter_test widget size assertions
All normal text elements pass 4.5:1 minimum colour contrast ratio; large text (18pt+ or 14pt bold) passes 3:1 minimum ratio
All icons and non-text UI elements that convey meaning pass 3:1 contrast ratio against adjacent backgrounds
Focus traversal order through ExpenseTypePickerWidget and ExpenseCalculationPreview is logical and matches reading order (top-to-bottom, left-to-right)
Every interactive element (buttons, toggles, pickers) has a non-empty Semantics label accessible to VoiceOver and TalkBack screen readers
No WCAG 2.2 AA violations remain after fixes; audit report documents all findings and their resolutions
ExpenseCalculationPreview dynamically updates its Semantics values when amounts change so screen readers announce new totals
Color is never the sole means of conveying expense type information; icons or text labels accompany all color-coded elements
All violations discovered during audit are fixed within the same task; no open violations are deferred
A written audit summary (checklist + pass/fail per criterion) is committed alongside the code changes

Technical Requirements

frameworks
Flutter
flutter_test
flutter_driver
data models
ExpenseType
ExpenseCalculation
performance requirements
Semantics tree generation must not add more than 2ms to widget build time
Accessibility audit tests must complete within 30 seconds in CI
security requirements
No sensitive financial values may be exposed unmasked in Semantics labels visible to accessibility services without user consent
ui components
ExpenseTypePickerWidget
ExpenseCalculationPreview
Semantics wrappers
ExcludeSemantics where decorative

Execution Context

Execution Tier
Tier 7

Tier 7 - 84 tasks

Can start after Tier 6 completes

Implementation Notes

Start by running Flutter's built-in `SemanticsDebugger` overlay in a debug build and manually tab through both widgets with keyboard navigation enabled. Use `Semantics(label: '...', button: true, child: ...)` wrappers wherever Flutter does not auto-generate correct labels (e.g., custom-painted widgets, icon-only buttons). For touch targets smaller than 44dp, wrap in a `GestureDetector` or `InkWell` with explicit `minimumSize` or use a `SizedBox` constraint — do not resize visible UI, use `Padding` or `ConstrainedBox` instead. For contrast: extract all colour pairs used in these two widgets from the design token system and compute ratios programmatically using the WCAG luminance formula.

Fix by adjusting token values, not by hardcoding hex values. Avoid using `ExcludeSemantics` on elements that carry meaning. Particular attention required for disabled/muted expense types — grey text on dark backgrounds often fails 4.5:1.

Testing Requirements

Write flutter_test widget tests using `tester.getSemantics()` to assert Semantics labels are present and non-empty for every interactive element. Use `findsWidgets` with `SemanticsFlag.isButton` and `SemanticsFlag.isFocusable`. Assert touch target sizes with `tester.getSize(find.byType(X)).width >= 44` (logical pixels). Use a contrast-checking utility or manually verify design token colour pairs against WCAG 4.5:1 ratio with a script.

Run the full test suite on both light and dark themes. Include regression tests that prevent future regressions by asserting Semantics labels are not empty strings.

Component
Expense Type Picker Widget
ui medium
Epic Risks (2)
medium impact medium prob technical

If the expense calculation preview subscribes to the full BLoC state stream, every unrelated state property change (e.g. a loading flag toggle) triggers a widget rebuild. With complex card animations for the disabled-state transition, this could cause frame drops on low-end Android devices used by some peer mentors.

Mitigation & Contingency

Mitigation: Use select() on the Riverpod provider to subscribe only to the specific state slice each widget needs; write a performance test asserting rebuild count on a rapid sequence of toggle events.

Contingency: If jank is detected in device testing, replace animated disabled-state transitions with instant opacity changes and defer animation polish to a follow-up sprint.

medium impact low prob integration

The disabled card state requires a specific contrast-safe colour combination that communicates unavailability without relying solely on colour (WCAG 1.4.1). If the current design token palette does not include a disabled-state token with sufficient contrast for text on the disabled background, the widget will either fail WCAG AA or require a last-minute design token addition that could break other components.

Mitigation & Contingency

Mitigation: Audit the existing design token manifest for disabled-state tokens at the start of the epic; if missing, raise with the design lead and add a contrast-validated token before widget implementation begins.

Contingency: If no design review is available, use the established --color-text-disabled and --color-surface-disabled tokens with an added strikethrough or lock icon to satisfy WCAG 1.4.1 non-colour requirement, and document the deviation for design review.