aria-live="assertive" blocks label from being read
See original GitHub issueIssue: If you associate a form label with a react-select input, the label is never announced by a screen reader.
Replication: Example here: https://codesandbox.io/s/n0q28p50xp Tested using react-select v2, VoiceOver and Safari.
Expected behavior: When native select element is associated with a label, a screen reader will read the label when the select receives focus.
Actual behavior:
Instead, when the react-select input receives focus, the screen reader is interrupted and begins immediately reading the contents of the A11yText
component (which are manually generated by react-select and don’t support including label text) because that component uses aria-live="assertive"
.
Impact: Without being able to associate a label with the input in a form, this component is not compliant with WCAG 2.0 accessibility guidelines (https://www.w3.org/TR/UNDERSTANDING-WCAG20/minimize-error-cues.html)
Possible solutions include:
- Using
aria-live="polite"
instead of"assertive"
(better practice, anyway, since you don’t know what else in the application/website the screen reader might be needing to keep track of) - Adding a new optional prop where form label text could be passed to the
A11yText
component - Allowing an
id
prop to be passed to the native input element
Issue Analytics
- State:
- Created 5 years ago
- Reactions:6
- Comments:5
Top GitHub Comments
Worth noting the assertive aria-live region can’t be rendered “on the fly”. Instead, it needs to be in the DOM since the beginning and stay there to allow screen readers to “monitor” changes within it.
Especially on Windows, screen readers “buffer” the content of a page. Instead, VoiceOver on macOS has a different behavior. This is very likely the reason why testing on different operating systems with different browser / screen reader combinations highlights inconsistent behaviors in the way the live messages are announced:
This behavior is more similar to the one of an ARIA
role="alert"
and seems triggered by the way Safari / VoiceOver perceive an aria-live region that is rendered “on the fly” in the DOM. Instead, aria-live regions are supposed to work differently and only changes within their content should be announced.The last behavior (part of the option is announced) can be explained better with the screenshot below:
When changing the highlighted option from
Green
toForest
, the partre
is ignored because it doesn’t “change”. BothGreen
andForest
containre
. The part that is perceived as “changed” is announced asFost
.The two complete strings for the example above are as follows:
option Green focused, 7 of 10. 10 results available. Use Up and Down to choose options, press Enter to select the currently focused option, press Escape to exit the menu, press Tab to select the option and exit the menu.
option Forest focused, 8 of 10. 10 results available. Use Up and Down to choose options, press Enter to select the currently focused option, press Escape to exit the menu, press Tab to select the option and exit the menu.
Please notice that only part of the option name and the option number are announced. All the rest of the string doesn’t change and it’s ignored.
This happens because the aria-relevant and aria-atomic attributes are missing so the default behavior is to announce only the “changed node”. Although it’s not 100% clear to me what a “changed node” is in this context, it’s pretty clear some screen readers announce just part of the string and ignore parts they don’t perceive as “changed” parts. Specifying
aria-relevant="additions text" aria-atomic="true"
may help.Additionally (not strictly related;
To recap, there would be the need to improve a few things to make the aria-live region work as expected:
Aria-live regions can be a bit tricky to implement. I’d like to suggest to consider to use the
@wordpress/a11y
package. It takes care of creating the live regions as soon as the DOM is ready. It takes a string for the message and an optional param for polite / assertive.Related: #2456
I want to be able to have a label for a creatable select that is announced properly by the screen reader. I was hoping that the update to the latest react-select with Alison Hall’s PR would fix it, but it doesn’t. I have set inputId to a value and then set htmlFor in my label to that value. I am using a Mac with Chrome with VoiceOver.
It would also be nice if the demo site was accessible. It currently doesn’t have labels for its inputs (it uses headers instead). That way if there is a specific way to associate the label and the input, there would be an example.