Skip to content

fix(core): announce Selector search result counts to screen readers#3725

Open
bhamodi wants to merge 1 commit into
facebook:mainfrom
bhamodi:a11y/selector-results-announce
Open

fix(core): announce Selector search result counts to screen readers#3725
bhamodi wants to merge 1 commit into
facebook:mainfrom
bhamodi:a11y/selector-results-announce

Conversation

@bhamodi

@bhamodi bhamodi commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Summary

In hasSearch mode, typing into the Selector popover's search input filters the option list silently. The filteredItems memo recomputes on every keystroke (Selector.tsx:640-648) and renderOptions swaps in a visual "No results found" empty state (Selector.tsx:911), but nothing was announced to assistive technology -- the file never imported useAnnounce. A screen-reader user narrowing a long list heard only their own typing, with no signal for how many options remained or that the list had emptied.

Typeahead already gives this feedback: BaseTypeahead announces result counts as you type via the repo's useAnnounce hook (BaseTypeahead.tsx:431-438). This brings Selector to parity, reusing the exact same strings -- `${n} result${n === 1 ? '' : 's'}` and "No results found" -- routed through the same hook and its persistently-mounted polite live region.

An effect keys off the existing filteredItems memo and the search state (Selector.tsx:691-706), so it covers every way the filtered list changes through one code path and adds no new prop or render branch. It announces only while the popover is open with a non-empty query; when the query is emptied or the popover closes it clears the region so stale status text does not linger.

Changes

  • Selector/Selector.tsx: import useAnnounce; add an effect that announces "3 results" / "1 result" / "No results found" politely while searching (matching BaseTypeahead's exact wording), and clears the region when the search context goes away.

Test plan

  • node_modules/.bin/vitest run --root . packages/core/src/Selector -- 49 pass (Selector.test.tsx). Four new tests under hasSearch > result announcements:
    • announces the match count politely while searching ("2 results")
    • announces the singular form when one option matches (asserted against /^1 result$/ so it cannot pass on a plural "1 results")
    • announces "No results found" when nothing matches
    • does not announce results until the user searches (closed popover / empty query)
    • The three positive-announcement tests were confirmed failing before the fix; the "does not announce" test guards against announcing on open or when idle.
  • node_modules/.bin/tsc --project packages/core/tsconfig.json --noEmit -- clean.
  • node_modules/.bin/eslint on changed files -- clean.

Notes

Found during a broader a11y audit of core components; scoped to one fix per PR (does not add the separate Home/End key-handling finding or touch other Selector behavior). Selector.doc.mjs was left unchanged: no new props were added and it has no accessibility/features section, matching how the analogous Typeahead announce behavior is not documented there either.

@vercel

vercel Bot commented Jul 9, 2026

Copy link
Copy Markdown

@bhamodi is attempting to deploy a commit to the Meta Open Source Team on Vercel.

A member of the Team first needs to authorize it.

@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Meta Open Source bot. label Jul 9, 2026
@bhamodi bhamodi force-pushed the a11y/selector-results-announce branch from 988bdae to 009c67f Compare July 9, 2026 06:40
@bhamodi bhamodi force-pushed the a11y/selector-results-announce branch from 009c67f to 64818b6 Compare July 9, 2026 06:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Meta Open Source bot.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant