medium priority low complexity frontend pending frontend specialist Tier 5

Acceptance Criteria

When LoginFormBLoC emits a loading state, a full-screen overlay appears above the LoginScreen content
The overlay background is semi-transparent (e.g., Colors.black.withOpacity(0.4)) to dim the content beneath without completely obscuring it
A CircularProgressIndicator is centred on the overlay, styled with the design-token primary colour
The overlay is wrapped in AbsorbPointer(absorbing: true) so all tap and gesture events are blocked while loading, preventing double-submission
The overlay includes a Semantics widget with liveRegion: true and label: 'Signing in, please wait' so screen readers announce the loading state immediately when it appears
When the BLoC transitions out of loading state (success or error), the overlay is removed immediately without a linger delay
The overlay is implemented using a Stack — the screen content is the first child, and the overlay is conditionally added as the second child based on BLoC state
The overlay does not use showDialog or any modal route — it is part of the screen widget tree to ensure AbsorbPointer works correctly
On loading state, the submit button inside LoginForm also reflects disabled state (already handled by task-005) — the overlay provides an additional layer of protection

Technical Requirements

frameworks
Flutter
BLoC
flutter_bloc
performance requirements
Overlay appearance and disappearance must be instant (no animation required) to avoid UX confusion about whether the action was triggered
security requirements
AbsorbPointer must cover the entire screen — verify the Stack child covers screen edges including safe areas
ui components
Stack
AbsorbPointer
Container (semi-transparent barrier, full screen)
CircularProgressIndicator
Semantics (liveRegion: true, label: 'Signing in, please wait')

Execution Context

Execution Tier
Tier 5

Tier 5 - 253 tasks

Can start after Tier 4 completes

Implementation Notes

In _LoginScreenBody (from task-007), wrap the entire Scaffold body in a BlocBuilder that returns a Stack. Stack children: [existing_screen_content, if (state.isLoading) _LoadingOverlay()]. Extract the overlay to a private stateless widget _LoadingOverlay for clarity. The overlay widget: return AbsorbPointer(absorbing: true, child: Container(color: Colors.black.withOpacity(0.4), child: Center(child: Semantics(liveRegion: true, label: 'Signing in, please wait', child: CircularProgressIndicator(color: AppColors.primary))))).

Use SizedBox.expand() on the Container or ensure it fills the Stack by positioning. This pattern (Stack + conditional overlay child) is preferred over Overlay.of(context) insertions for screen-scoped loading states because it stays within the widget tree and is automatically removed with the screen. This accessibility pattern is especially important for users of screen readers (VoiceOver on iOS, TalkBack on Android) — a common need given the target audience includes visually impaired users from Blindeforbundet.

Testing Requirements

Write widget tests using flutter_test and a mock LoginFormBLoC: (1) when state is not loading, no overlay widget is in the tree, (2) when state is loading, a Container with semi-transparent colour is present, (3) when state is loading, an AbsorbPointer with absorbing:true wraps the overlay, (4) when state is loading, Semantics with liveRegion:true and correct label is present, (5) when loading state ends, overlay is gone. Verify AbsorbPointer by attempting a tap on the submit button during loading state and asserting no new BLoC events are dispatched.

Component
Login Screen
ui low
Epic Risks (3)
high impact medium prob scope

Automated accessibility checks (e.g., flutter_accessibility_service) may pass while manual VoiceOver/TalkBack testing reveals focus-order issues, missing semantic roles, or live region announcements that fire too early or not at all. Discovering these late risks delaying the MVP release.

Mitigation & Contingency

Mitigation: Conduct manual VoiceOver and TalkBack testing on physical devices at the end of every sprint, not only at release. Define accessibility acceptance criteria per component and include them in the DoD. Use Semantics widgets explicitly rather than relying on implicit semantics from Flutter's default widgets for all interactive elements.

Contingency: Maintain a prioritized accessibility bug backlog separate from the main backlog. If critical VoiceOver issues are found close to release, create an explicit accessibility hotfix sprint before TestFlight distribution to Blindeforbundet testers.

medium impact medium prob technical

Keyboard height varies significantly between iOS and Android, between device sizes (iPhone SE vs iPad), and with third-party keyboards. The KeyboardAwareLayout may not correctly adjust scroll offset in all combinations, causing input fields to remain hidden behind the keyboard on certain device/keyboard configurations.

Mitigation & Contingency

Mitigation: Test on a matrix of devices including iPhone SE (small viewport), a mid-size Android phone, and a tablet. Implement the layout using MediaQuery.viewInsets.bottom rather than a fixed padding value to correctly respond to any keyboard height. Include edge cases for floating keyboards on iPads.

Contingency: If device-specific issues are found after release, implement a bottom-padding fallback using BottomPadding inset and allow users to manually scroll. Log affected device/OS combinations for targeted fixes.

high impact low prob dependency

If the design token system's colour palette is updated without re-running contrast validation, form field labels, error messages, or placeholder text could fall below the WCAG 2.2 AA 4.5:1 ratio, causing a compliance regression.

Mitigation & Contingency

Mitigation: Integrate a contrast ratio validator (e.g., a CI lint step using the contrast-ratio-validator component) that checks all colour pairs used in the login form on every pull request. Document which token pairs are used for labels, errors, and backgrounds in the login form.

Contingency: If a contrast regression is detected post-merge, hot-patch the affected design token value. Do not ship a TestFlight build with known WCAG AA failures to Blindeforbundet testers.