high priority medium complexity frontend pending frontend specialist Tier 3

Acceptance Criteria

All interactive elements (Export button, diff toggle, section headers if tappable, Cancel/Export-anyway dialog buttons) have explicit Semantics labels generated via BufdirAccessibilityUtils.labelFor()
Focus traversal order matches visual top-to-bottom, left-to-right reading order when using keyboard or switch access
Validation banner liveRegion=true causes VoiceOver/TalkBack to announce banner appearance/content without user interaction
Export button Semantics includes both a label ('Export report') and a hint ('Double tap to export or review warnings')
Diff toggle Semantics includes current state ('Diff panel collapsed' / 'Diff panel expanded') as a value property
Every tappable element has a minimum touch target of 48×48 dp — verified programmatically via widget bounds in tests
Text contrast ratio for all visible text on the screen meets WCAG 2.2 AA (4.5:1 normal text, 3:1 large text) — verified against the design token palette
flutter_test accessibility checker (tester.ensureSemantics() + SemanticsGuideline.androidTapTargetGuideline) passes with zero violations
Screen reader navigation: a user can reach Export button, diff toggle, and all section headers using sequential focus without encountering a focus trap
No semantic node has an empty or null label on any interactive widget

Technical Requirements

frameworks
Flutter
flutter_test
performance requirements
Semantics overhead must not add measurable frame time — Semantics widgets should only wrap leaf or near-leaf widgets, not entire subtrees unnecessarily
security requirements
Semantics labels must not expose internal IDs, database keys, or system paths — use only user-facing display strings
ui components
Semantics widget (wrapping interactive elements)
MergeSemantics (where grouping improves comprehension)
ExcludeSemantics (for decorative/redundant elements)
FocusTraversalGroup (to enforce focus order)

Execution Context

Execution Tier
Tier 3

Tier 3 - 413 tasks

Can start after Tier 2 completes

Implementation Notes

Use BufdirAccessibilityUtils as a static utility class with named methods (e.g. exportButtonLabel(), diffToggleLabel(isExpanded), sectionHeaderLabel(sectionTitle)) to centralise all label strings — this makes future internationalisation straightforward. Use FocusTraversalGroup with ReadingOrderTraversalPolicy around the AppBar actions to guarantee left-to-right order regardless of widget insertion order. For the diff toggle, use Semantics(toggled: isExpanded, label: ...) rather than a plain label so switch-access users understand the current state.

Run the built-in Flutter accessibility audit: add a test that calls tester.runAsync(() => tester.pumpWidget(...)) and then checks await tester.getSemantics(find.byType(BufdirPreviewScreen)) — ensure zero violations. Check colours against the design token definitions, not hardcoded values, so that theme changes are automatically verified.

Testing Requirements

Write dedicated accessibility widget tests using flutter_test. Enable semantics handle at the start of each test with tester.ensureSemantics(). Assert: (1) SemanticsAction.tap is available on Export button and diff toggle, (2) liveRegion is true on validation banner root, (3) androidTapTargetGuideline passes for all tappable widgets, (4) iOSTapTargetGuideline passes for all tappable widgets, (5) labeledTapTargetGuideline passes (no unlabelled tappable nodes). Also run a focus traversal test: simulate repeated Tab key presses and verify the focus order matches the expected sequence.

Document any ExcludeSemantics decisions with a comment explaining why the element is excluded.

Component
Bufdir Report Preview Screen
ui high
Epic Risks (3)
medium impact medium prob integration

The preview screen must pass period, scope, and aggregation session state to the Bufdir Report Export screen via navigation arguments. If the export screen's navigation argument schema is not yet finalized when this epic begins, the handoff will require rework — potentially after TestFlight is already in use by coordinators.

Mitigation & Contingency

Mitigation: Define the shared BufdirExportNavigationArgs Dart class jointly with the Bufdir Report Export feature team before this epic starts. Store it in a shared models package both features depend on. Treat the class as an API contract with a minor-version bump policy.

Contingency: If the export screen's argument schema changes after the preview screen is implemented, the BufdirPreviewService session state model can be adapted with a compatibility shim. The preview screen itself requires only a one-line navigation call change.

medium impact low prob technical

The period diff view loads prior-period data on demand and renders it inline with the current report. On a large report (many sections, many fields) combined with slow Supabase connectivity, the diff overlay could block the UI or produce a janky re-render that degrades the coordinator experience during the pre-submission review.

Mitigation & Contingency

Mitigation: Load prior-period data in a background Riverpod FutureProvider that starts prefetching when the preview screen mounts (not when the user taps the diff toggle). Show a shimmer placeholder on each field row's prior-period column while loading. Cache prior-period data in BufdirPreviewRepository using the same local cache as current-period data.

Contingency: If diff view performance is unacceptable on TestFlight devices, disable the toggle for the initial TestFlight release and ship the diff view in the following sprint after profiling the Supabase query plan and adding an appropriate Postgres index on the prior-period data table.

high impact medium prob scope

The full preview screen will be reviewed by coordinators on TestFlight who will cross-reference it against their physical Bufdir reporting forms. Any section ordering difference or label mismatch discovered during UAT will require a fix before the feature can be signed off, potentially delaying the entire Bufdir reporting pipeline.

Mitigation & Contingency

Mitigation: Conduct a pre-TestFlight alignment review with at least one coordinator from NHF and one from HLF using a static screenshot of the preview screen layout. Obtain written sign-off on section order and field labels before distributing to the full test group of 5-8 people.

Contingency: If label mismatches are found during TestFlight UAT, update BufdirReportStructureMapper constants and rebuild. Since the mapper is a pure Dart class with no persisted state, corrections are deployed in the next TestFlight build with no database migration required.