diff --git a/native/src/components/CitySelector.tsx b/native/src/components/CitySelector.tsx
index 9f70fd07b0..331ead743d 100644
--- a/native/src/components/CitySelector.tsx
+++ b/native/src/components/CitySelector.tsx
@@ -1,7 +1,7 @@
import { groupBy, transform } from 'lodash'
-import React, { ReactElement, ReactNode, useState } from 'react'
+import React, { ReactElement, ReactNode, useEffect, useState } from 'react'
import { useTranslation } from 'react-i18next'
-import { View } from 'react-native'
+import { AccessibilityInfo, Platform, View } from 'react-native'
import styled from 'styled-components/native'
import { filterSortCities } from 'shared'
@@ -43,6 +43,13 @@ const CitySelector = ({ cities, navigateToDashboard }: CitySelectorProps): React
const resultCities = filterSortCities(cities, filterText, buildConfig().featureFlags.developerFriendly)
+ useEffect(() => {
+ // iOS doesn't have live regions to inform a user with a screenreader that there are no more search results
+ if (resultCities.length === 0 && Platform.OS === 'ios') {
+ AccessibilityInfo.announceForAccessibility(t('searchResultsCount', { count: 0 }))
+ }
+ }, [resultCities, t])
+
const renderCity = (city: CityModel) => (
)
@@ -76,7 +83,9 @@ const CitySelector = ({ cities, navigateToDashboard }: CitySelectorProps): React
{t('nearbyCities')}
- {t('search:searchResultsCount', { count: resultCities.length })}
+
+ {t('search:searchResultsCount', { count: resultCities.length })}
+
{resultCities.length === 0 ? : cityEntries}
diff --git a/native/src/routes/SearchModal.tsx b/native/src/routes/SearchModal.tsx
index 9e7da908ea..50afb0aad1 100644
--- a/native/src/routes/SearchModal.tsx
+++ b/native/src/routes/SearchModal.tsx
@@ -1,6 +1,6 @@
-import React, { ReactElement, useState } from 'react'
+import React, { ReactElement, useEffect, useState } from 'react'
import { useTranslation } from 'react-i18next'
-import { KeyboardAvoidingView, Platform } from 'react-native'
+import { AccessibilityInfo, KeyboardAvoidingView, Platform } from 'react-native'
import styled from 'styled-components/native'
import { parseHTML, SEARCH_FINISHED_SIGNAL_NAME, SEARCH_ROUTE, SearchResult, useSearch } from 'shared'
@@ -48,6 +48,13 @@ const SearchModal = ({
const searchResults = useSearch(allPossibleResults, query)
+ useEffect(() => {
+ // iOS doesn't have live regions to inform a user with a screenreader that there are no more search results
+ if (searchResults?.length === 0 && Platform.OS === 'ios') {
+ AccessibilityInfo.announceForAccessibility(t('searchResultsCount', { count: 0 }))
+ }
+ }, [searchResults, t])
+
if (!searchResults) {
return null
}
@@ -82,7 +89,9 @@ const SearchModal = ({
{query.length > 0 && (
<>
- {t('searchResultsCount', { count: searchResults.length })}
+
+ {t('searchResultsCount', { count: searchResults.length })}
+
placeholderText={t('searchCity')}
spaceSearch={false}
onStickyTopChanged={setStickyTop}>
- {t('search:searchResultsCount', { count: resultCities.length })}
+
+ {t('search:searchResultsCount', { count: resultCities.length })}
+
{resultCities.length === 0 ? : groups}
diff --git a/web/src/routes/SearchPage.tsx b/web/src/routes/SearchPage.tsx
index e145501fd0..b9b429916e 100644
--- a/web/src/routes/SearchPage.tsx
+++ b/web/src/routes/SearchPage.tsx
@@ -107,7 +107,9 @@ const SearchPage = ({ city, cityCode, languageCode, pathname }: CityRouteProps):
{query.length > 0 && (
<>
- {t('searchResultsCount', { count: results.length })}
+
+ {t('searchResultsCount', { count: results.length })}
+
{results.map(({ title, content, path, thumbnail }) => (