Implement PasswordVisibilityToggle widget
epic-email-password-login-ui-task-001 — Build the PasswordVisibilityToggle as an accessible icon button embedded within the password input field. Must meet 48x48dp minimum touch target size requirement, include a semantic screen reader label (e.g., 'Show password' / 'Hide password'), and toggle the obscureText state of the parent AppTextField. Use Semantics widget with label and hint properties.
Acceptance Criteria
Technical Requirements
Implementation Notes
Implement as a stateless widget with signature: PasswordVisibilityToggle({required bool isVisible, required VoidCallback onToggle}). Wrap IconButton in a SizedBox with width and height of 48 to guarantee touch target size — do not rely on the theme's default IconButton splash radius alone. Use Semantics with label and button: true properties wrapping the IconButton. Pull icon colours from the design token system (e.g., AppColors.iconSecondary) rather than hardcoding hex values, so the widget automatically adapts to organisation theming.
This widget is part of the shared widget library used across all three organisations (NHF, Blindeforbundet, HLF) so accessibility requirements are non-negotiable.
Testing Requirements
Widget tests using flutter_test: verify initial state renders visibility_off icon and Semantics label 'Show password'; verify tap produces visibility icon and label 'Hide password'; verify tap again restores initial state; verify touch target size is ≥48x48 via tester.getSize(). Accessibility test: use flutter_test's SemanticsController to assert that the node has the correct label and is focusable. Golden test for visual regression at standard density. All tests must pass without platform channels.
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.
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.
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.