critical priority low complexity frontend pending frontend specialist Tier 0

Acceptance Criteria

AccessibleSearchInputField is a stateless or stateful Flutter widget that wraps the existing AppTextField
The widget includes a Semantics node with a non-empty label describing the search field purpose (e.g., 'Search contacts')
The Semantics node includes a hint string describing the expected input (e.g., 'Enter name or role')
The clear button is a separate focusable widget with its own Semantics(label: 'Clear search') node
The widget is navigable in order via keyboard tab/arrow focus and switch access traversal
Focus order follows logical reading order: search field first, clear button second
Text contrast meets WCAG 2.2 AA (4.5:1 for normal text, 3:1 for large text) using design token colors
The widget accepts onChanged, onSubmitted, onClear, controller, and focusNode as constructor parameters
The widget integrates with AppTextField's existing design token styling — no raw Color literals
Clear button is hidden (opacity 0 or removed from tree) when the field is empty to avoid presenting a non-functional action to screen readers

Technical Requirements

frameworks
Flutter
performance requirements
Widget rebuild must not cause parent subtree to rebuild — use const constructors where possible
security requirements
Input field must not autocomplete or cache sensitive search queries via autofillHints
ui components
AppTextField (existing reusable widget)
Semantics (Flutter framework)
Focus (Flutter framework)
FocusTraversalGroup
IconButton (clear action)
Design token color/typography constants

Execution Context

Execution Tier
Tier 0

Tier 0 - 440 tasks

Implementation Notes

Wrap the root of the widget with FocusTraversalGroup using ReadingOrderTraversalPolicy to enforce field → clear button focus order. Use Semantics with label and hint parameters directly — avoid MergeSemantics unless you need to collapse child nodes intentionally. For the clear button: use AnimatedOpacity or Visibility(maintainState: false) conditioned on controller.text.isNotEmpty so it disappears from both the visual layer and the semantics tree when not relevant. Do not use textField: true on the Semantics node wrapping AppTextField — AppTextField already provides its own semantics from the underlying TextField; adding textField: true on a parent node would create a duplicate announcement.

Instead, annotate only the outer container with label and hint, and rely on the inner TextField's native semantics for text-field role announcement. Expose a FocusNode parameter so the parent screen can programmatically focus the field (e.g., on screen load).

Testing Requirements

Widget-test AccessibleSearchInputField: (1) renders with AppTextField as a descendant, (2) Semantics node has correct label and hint via tester.getSemantics(), (3) clear button Semantics node has label 'Clear search', (4) clear button is absent from semantics tree when field is empty, (5) onChanged fires when text is entered, (6) onClear fires when clear button is tapped and field is empty afterward, (7) FocusTraversalGroup orders field before clear button. Use flutter_test SemanticsHandle for semantic assertions. No golden tests required for this task.

Epic Risks (2)
medium impact medium prob technical

Flutter's Semantics live region support for announcing dynamic result count changes may behave inconsistently between VoiceOver (iOS) and TalkBack (Android), particularly regarding announcement throttling and focus management, causing the feature to pass testing on one platform and fail on the other.

Mitigation & Contingency

Mitigation: Test live region announcements on both iOS (VoiceOver) and Android (TalkBack) early in development using the existing accessibility test harness. Reference the existing LiveRegionAnnouncer component (608-live-region-announcer) patterns used elsewhere in the app.

Contingency: If cross-platform consistency cannot be achieved, implement a platform-specific announcement strategy using the SemanticsService.announce API with platform-conditional announcement timing to work around OS-specific throttling behaviour.

low impact low prob dependency

Voice-to-text progressive enhancement for Blindeforbundet may not be available or may behave unpredictably on all device/OS combinations, particularly older Android devices, potentially causing crashes or silent failures that degrade the search experience.

Mitigation & Contingency

Mitigation: Implement voice-to-text as a strictly optional enhancement: detect availability at runtime, show the microphone button only when the platform speech API reports availability, and wrap all voice invocations in try/catch with graceful degradation to standard text input.

Contingency: If voice-to-text causes instability on a subset of devices discovered during TestFlight/beta, disable the feature flag for that platform version while a fix is investigated, without impacting the core text-based search functionality.