high priority low complexity frontend pending frontend specialist Tier 0

Acceptance Criteria

Widget renders exactly three selectable cards: Excel (.xlsx), CSV (.csv), PDF (.pdf) — in that display order
Each card contains: (1) file-type icon using a design-token-sized icon asset or Material icon, (2) format name as primary text, (3) a short Bufdir compatibility note as secondary text (e.g., 'Recommended for Bufdir import' for Excel)
Tapping a card selects it, applies a visible active-state border/background using design token colors, and invokes onFormatSelected(BufdirExportFormat format) callback
Only one card can be selected at a time; selecting a new card deselects the previous one
Widget supports an optional initialFormat parameter to pre-select a format on first render (defaults to Excel as the Bufdir-recommended format)
All text/background color combinations meet WCAG 2.2 AA contrast ratio of 4.5:1 (verified with design tokens)
Focus traversal follows reading order (Excel → CSV → PDF) and each card is keyboard/switch-access activatable
Each card has a Semantics label describing its state: e.g., 'Excel format, recommended for Bufdir, selected' / 'not selected'
No inline styles — all visual values from design token system
Widget tests confirm single-selection invariant and callback emission

Technical Requirements

frameworks
Flutter
data models
BufdirExportFormat (enum: excel, csv, pdf)
performance requirements
Widget uses const card constructors; rebuilds only the previously and newly selected cards on tap (not entire list)
security requirements
Format selection is a UI preference only — actual file generation is server-side; no validation required at this layer
ui components
BufdirExportFormatSelector (stateful widget)
ExportFormatCard (reusable card with selected/unselected states)
FileTypeIcon (maps BufdirExportFormat to icon asset)

Execution Context

Execution Tier
Tier 0

Tier 0 - 440 tasks

Implementation Notes

Model formats as a BufdirExportFormat enum with a metadata extension: displayName, fileExtension, bufdirNote, iconData. This keeps the card widget free of business logic. Use a simple selectedFormat state variable inside a StatefulWidget — no BLoC needed for this isolated widget. The active card border should use a design token like AppColors.primary with AppBorderRadius.md.

Use IndexedSemantics or explicit Semantics(selected: isSelected) on each card so screen readers announce selection changes. Pre-select Excel by default as it is the Bufdir-standard import format per project documentation. Export the enum and widget from a single barrel file.

Testing Requirements

Write flutter_test widget tests: (1) all three cards render with correct labels, (2) tapping Excel fires onFormatSelected(BufdirExportFormat.excel), (3) tapping CSV after Excel deselects Excel and selects CSV — callback fires once with CSV, (4) initialFormat pre-selects the correct card without firing callback, (5) Semantics labels reflect selected/unselected state accurately, (6) no overflow at text scale 1.5×. Snapshot test the three-card layout at 375 px width (iPhone SE) and 414 px width (iPhone Pro).

Component
Export Format Selector
ui low
Epic Risks (2)
medium impact medium prob technical

For large exports that run for 10–30 seconds, a static loading spinner will feel broken to users on slow mobile connections. If the UI cannot display meaningful progress during the export pipeline, coordinators may abandon the flow or trigger duplicate exports by pressing the button multiple times.

Mitigation & Contingency

Mitigation: Implement streaming progress events from the orchestrator BLoC through named pipeline stages (querying, mapping, generating, uploading). Display each stage label with a progress indicator on the trigger screen. Disable the generate button immediately on first tap to prevent duplicates.

Contingency: If streaming pipeline progress is not feasible in the first release, implement a deterministic stage-based progress animation (10% querying, 50% generating, 90% uploading) that gives users feedback without requiring real server events.

high impact medium prob technical

Custom date range pickers are among the most common accessibility failures in mobile apps. Blindeforbundet users rely on VoiceOver, and NHF users include people with cognitive impairments. A non-accessible period picker could make the entire export workflow unusable for a significant portion of the intended user base.

Mitigation & Contingency

Mitigation: Build the period picker using Flutter's native date picker semantics as the foundation, with preset shortcuts as primary navigation (reducing the need to interact with the custom range picker at all). Test with VoiceOver on iOS and TalkBack on Android before UI epic sign-off. Engage Blindeforbundet's test contact for accessibility validation.

Contingency: If the custom date range picker cannot be made fully accessible before release, ship only the preset period shortcuts (covering the majority of use cases) and add the custom range picker in a follow-up sprint after dedicated accessibility remediation.