high priority low complexity frontend pending frontend specialist Tier 1

Acceptance Criteria

OnboardingProgressIndicator is rendered at the top of OrgSelectionScreen's content area, above the org list
The indicator shows the current step number and total steps (e.g., 'Step 1 of 3')
The step label text reads 'Choose your organization' (or the localized equivalent) for the org selection step
The indicator is wrapped in a Visibility or Offstage widget and is hidden when the user has previously completed onboarding (onboardingComplete flag is true in user state)
The onboardingComplete flag is read from a Cubit/provider — not from shared preferences directly in the widget
A Semantics widget wraps the indicator with a label such as 'Onboarding step 1 of 3: Choose your organization'
The indicator does not appear during a context-switch flow (returning user switching orgs from MultiOrgContextSwitcher)
Widget test confirms the indicator is visible for new users and hidden for returning users
Widget test confirms the semantic label is correctly set
The OnboardingProgressIndicator widget accepts currentStep and totalSteps as parameters and is reusable across other onboarding screens

Technical Requirements

frameworks
Flutter
flutter_bloc
data models
UserOnboardingState (isOnboardingComplete, currentStep, totalSteps)
performance requirements
Indicator visibility toggle must not cause layout jank — use Visibility with maintainState: false
ui components
OnboardingProgressIndicator widget (currentStep, totalSteps, stepLabel params)
Semantics wrapper with descriptive label
Visibility widget controlled by onboardingComplete flag

Execution Context

Execution Tier
Tier 1

Tier 1 - 540 tasks

Can start after Tier 0 completes

Implementation Notes

Create OnboardingProgressIndicator as a pure stateless widget with parameters: int currentStep, int totalSteps, String stepLabel. Wrap it in a Semantics node inside the widget itself so the semantic label is always correct regardless of where it is embedded. In OrgSelectionScreen, read onboardingComplete from the relevant Cubit (e.g., OnboardingCubit or UserSessionCubit) using BlocSelector to avoid rebuilding the whole screen on unrelated state changes. Use Visibility(visible: !isOnboardingComplete, child: OnboardingProgressIndicator(...)) — do not use conditional rendering with ternary null, as Visibility preserves layout space by default; set maintainSize: false, maintainAnimation: false, maintainState: false to fully collapse it.

The step count (1 of 3) should be a constant defined in the onboarding flow configuration, not hardcoded per screen.

Testing Requirements

Write widget tests: (1) OnboardingProgressIndicator renders with correct step text for given currentStep/totalSteps values, (2) indicator is hidden when UserOnboardingState.isOnboardingComplete is true, (3) indicator is visible when isOnboardingComplete is false, (4) Semantics label matches the expected string. Unit test the Cubit/state that exposes isOnboardingComplete. No integration or e2e tests required for this task. Use flutter_test.

Epic Risks (2)
low impact high prob technical

OrgSelectionScreen and OrgContextSwitcher render partner-specific logos, colors, and text from dynamic data. Golden tests (pixel-comparison screenshots) will fail whenever branding assets are updated in the backend, causing CI failures that block unrelated PRs and eroding developer trust in the test suite.

Mitigation & Contingency

Mitigation: Use fixture-based golden tests with static mock Organization models containing embedded test assets rather than network-fetched assets. Separate branding asset acceptance tests into a dedicated CI job that only runs on branding-related PRs and is maintained by the design team.

Contingency: If golden test maintenance overhead becomes excessive, replace pixel-comparison goldens with semantic widget tests that assert widget tree structure and key property values, reserving golden tests for only the most stable, design-critical elements.

high impact medium prob scope

Several partner organizations (especially Blindeforbundet) have users who rely entirely on VoiceOver or TalkBack. Complex branded card layouts with overlaid logos, names, and selection states are notoriously difficult to make fully accessible; missing semantics or incorrect focus order could make the selection screen completely unusable for screen reader users before launch.

Mitigation & Contingency

Mitigation: Involve an accessibility specialist in the design review before any widget implementation begins. Use Flutter's Semantics widget with explicit label, hint, and button role on OrgCardWidget. Conduct manual screen reader testing on both iOS (VoiceOver) and Android (TalkBack) for every sprint that touches these screens, not just before release.

Contingency: If full WCAG compliance cannot be achieved within the sprint, implement a simplified text-list fallback mode that activates when the system detects an active screen reader, presenting orgs as plain accessible list tiles instead of the branded card layout.