high priority low complexity frontend pending frontend specialist Tier 2

Acceptance Criteria

After each debounced query completes, VoiceOver (iOS) and TalkBack (Android) announce the result count without moving focus away from the search field
Announcement reads '3 results found' or 'No results found for <query>' in the device language
Announcement fires only after debounce settles (no announcement for every keystroke)
When results update from a previous non-empty query, announcement reflects new count accurately
Announcement does not fire on initial render before the user has typed anything
SemanticsService.announce() call is throttled so rapid successive queries do not stack announcements
Widget is covered by a dedicated unit test using flutter_test's SemanticsController

Technical Requirements

frameworks
Flutter
flutter_test
apis
SemanticsService.announce()
Flutter Semantics API
performance requirements
Announcement must fire within 100 ms after debounce completes
No additional widget rebuilds triggered solely by the announcement
security requirements
Announced text must not expose sensitive contact data beyond count
ui components
AccessibleSearchInputField
LiveRegionAnnouncer (new internal widget)

Execution Context

Execution Tier
Tier 2

Tier 2 - 518 tasks

Can start after Tier 1 completes

Implementation Notes

Prefer a small stateless LiveRegionAnnouncer widget that listens to a ValueNotifier (null = no query yet) rather than calling SemanticsService.announce() directly inside AccessibleSearchInputField — this keeps the announcement logic testable and decoupled. Use addPostFrameCallback to ensure announcement fires after the widget tree settles. Throttle with a simple bool flag or Timer to avoid announcement storms when the user pastes text. Do NOT use a Semantics widget with liveRegion: true on Flutter mobile — that attribute is web-only; SemanticsService.announce() is the correct cross-platform approach.

Pass the result count down from the parent via the existing state provider (Riverpod or BLoC) rather than introducing a separate stream.

Testing Requirements

Unit tests using flutter_test with SemanticsController: verify announce() is called with correct string after debounce, verify no announcement on initial render, verify throttling prevents duplicate announcements. Integration test: type in search field, await debounce, assert semantic announcement string. Manual VoiceOver and TalkBack verification on physical devices required before merge.

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.