high priority medium complexity frontend pending frontend specialist Tier 2

Acceptance Criteria

Email field shows an inline error message beneath the field when the submitted value is empty or not a valid email format
Password field shows an inline error message beneath the field when the submitted value is empty
Error messages appear on form submission attempt AND on field blur (focus leaving a field with invalid content)
Error text is passed via AppTextField's errorText parameter — not rendered as a separate widget outside AppTextField
Each error message is wrapped in Semantics(liveRegion: true, container: true) so screen readers (TalkBack/VoiceOver) announce it immediately when it appears
Error messages include a non-colour indicator (e.g., an error icon prefix or the word 'Error:') so WCAG 1.4.1 is satisfied — colour alone does not convey the error state
When a field's value becomes valid after an error was shown, the error text clears immediately on next change event
Field border/decoration changes to the design-token error colour when errorText is non-null (this is handled by AppTextField's existing decoration logic — verify it works)
Validation logic for email uses a regex that covers standard RFC 5322 simplified patterns (rejects obvious invalid inputs, does not over-validate)
No error is shown for a field that has never been touched (pristine state)

Technical Requirements

frameworks
Flutter
BLoC
performance requirements
Validation runs synchronously — no async validators for client-side format checks
Error state updates must be local to LoginForm and not trigger parent widget rebuilds
security requirements
Validation error messages must not leak server-side information — client-side messages only at this layer
Do not expose whether an email address exists in the system in field-level validation (existence check is a server concern)
ui components
AppTextField (errorText parameter)
Semantics (liveRegion: true wrapper for each error)
Error icon or prefix text (non-colour WCAG indicator)

Execution Context

Execution Tier
Tier 2

Tier 2 - 518 tasks

Can start after Tier 1 completes

Implementation Notes

Maintain a Map fieldErrors in LoginForm's state (keys: 'email', 'password'). On blur (onEditingComplete / FocusNode listener) and on submit, run _validateEmail() and _validatePassword() pure functions that return a String? error message or null. Call setState to update fieldErrors, then pass fieldErrors['email'] to the email AppTextField's errorText and fieldErrors['password'] to the password field's.

Wrap each AppTextField in a Column that includes a Semantics(liveRegion: true, child: Text(error)) widget — or confirm AppTextField already handles this internally; if not, add it externally. For WCAG 1.4.1, prefix each error string with an error icon character or 'Error: ' text so the message carries meaning independent of colour. Pristine tracking: use a Set _dirtyFields; only validate a field if it's in _dirtyFields (added on first change or on submit attempt).

Testing Requirements

Write widget tests using flutter_test covering: (1) submitting empty form shows both error messages, (2) submitting with invalid email format shows email error only, (3) valid email + empty password shows password error only, (4) blurring email field with invalid content shows email error without requiring submit, (5) correcting a field after error clears the error text, (6) Semantics tree contains liveRegion: true nodes when errors are visible. Use find.bySemanticsLabel and tester.semantics to assert accessibility tree. Use flutter_test's SemanticsController to verify live region announcements.

Component
Login Form
ui medium
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.