[EuiSelectable] Fix repeated screen reader announcement of results count#9555
Conversation
Pass a string instead of a React element to EuiScreenReaderLive by using EuiI18n render prop pattern. Previously, each re-render created a new React element reference for listScreenReaderStatus, causing EuiScreenReaderLive's useEffect to fire on every arrow key navigation and repeatedly announce the results count via aria-live region. Strings are compared by value, so the announcement now only triggers when the count actually changes. Closes elastic#9197
There was a problem hiding this comment.
Pull request overview
This PR updates EuiSelectable’s live screen reader status announcement to avoid repeatedly announcing the total results count during keyboard navigation, addressing #9197 by ensuring EuiScreenReaderLive only re-announces when the count actually changes.
Changes:
- Reworked the results-count live region content from a React element (
<EuiI18n />) to anEuiI18nrender-prop string to preventEuiScreenReaderLive’s[children]effect from firing on unrelated re-renders. - Added an upcoming changelog entry for the accessibility bug fix.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| packages/eui/src/components/selectable/selectable.tsx | Changes the live-region “results available” announcement to pass a stable string instead of a new React element per render. |
| packages/eui/changelogs/upcoming/9197.md | Documents the EuiSelectable screen reader announcement bug fix. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
Hey @yansavitski. I'm removing the Community Contribution label. We use that for contributions from outside of Elastic. I'm also removing the skip-changelong label, as this is a change and requires a changelog. |
|
Sorry for the delay on this, I had to look at this a bit more, as the duplication in screen readers is not reproducible in EUI, only in Kibana. That being said, I don't have a clearer answer to why the duplication only happens in Kibana. The most logical explanation imho is that the DOM changes on Overall, the proposed solution to stabilize the content passed to |
1d282c4 to
739b373
Compare
…een-reader-repeated-announcement
mgadewoll
left a comment
There was a problem hiding this comment.
🟢 The changes are LGTM and the update works as expected (tested on EUI as well as in Kibana). Thanks for digging into this and contributing to add a solution! 🎉
💚 Build SucceededHistory
|
💚 Build Succeeded
History
|
Summary
EuiSelectablerepeatedly announcing total results count on every arrow key navigation.stateinstructions for a11y #9197. Screen readers (NVDA on Windows) announce "X results available" on every option change instead of only when the count actually changes. Related Kibana issue: [AI Connector] (Accessibility): Total number of options announced before each option kibana#199463listScreenReaderStatusfrom being passed as a React element (<EuiI18n>) to being passed as a plain string viaEuiI18nrender prop pattern. React elements create new object references on every render, causingEuiScreenReaderLive'suseEffect([children])to fire on every re-render. Strings are compared by value, so the effect only triggers when the results count actually changes.API Changes
No API changes.
Screenshots
N/A — no visual changes, this is a screen reader behavior fix.
Impact Assessment
🔴 Breaking changes💅 Visual changes🔧 Hard to integrateImpact level: 🟢 None
Release Readiness
DocumentationFigmaMigration guideAdoption planQA instructions for reviewer
Reproducing with NVDA (Windows)
Verifying on macOS via DOM inspection
The root cause is that
aria-liveregions mutate on every arrow key press, which NVDA picks up and announces. This can be verified without NVDA by observing DOM mutations directly. Open the story in an iframe (/iframe.html?id=forms-euiselectable--with-search) and paste in DevTools Console:aria-livetoggles on every arrow key pressaria-livelogs during arrow navigation; logs appear only when typing in search (results count changes)Checklist before marking Ready for Review
aria-liveregion behavior via MutationObserverBreaking changes