Missing aria-live and aria-errormessage attributes in form field components
Background Information
Package Version(s):
- ui-form-field v10.14.0
- ui-select v10.14.0
- ui-simple-select v10.14.0
- ui-text-input v10.14.0
Browser: Chrome (observed), potentially all
Screen Reader: Mac VoiceOver (tested), potentially all
Component: FormFieldLayout, Select, SimpleSelect, TextInput
Describe the Issue
Accessibility issues in form field components:
-
Error messages are not automatically announced by screen readers due to missing
aria-liveandrole="alert"attributes -
The
aria-errormessageattribute is not being propagated from FormFieldLayout down to input elements -
The
aria-errormessageattribute does not match the ID of the error message container
Steps To Reproduce
- Render a Select or SimpleSelect with error messages
- Verify that input elements have
aria-invalidbut are missingaria-errormessage - Trigger form validation errors
- Error messages are not automatically announced (unless focus is on the invalid input)
Expected Behavior
-
Error message container should:
- Have
aria-live="assertive"androle="alert"for error messages - Be persistently in the DOM
- Have
-
Input elements should have both
aria-invalid="true"andaria-errormessagepointing to message container ID -
Error message container should have an ID matching
aria-errormessage
Additional Information
Current Workaround(s): At the moment we are duplicating error messages in a ScreenReaderContent with aria-live="assertive" and role="alert" to ensure they are announced
Products Affected: All form field components
Are you willing to submit a PR to fix?
- [x] Yes, I'm willing to submit a PR
- (I may have a speculative fix...)
WCAG Guidelines
- 1.3.1 Info and Relationships (Level A)
- 4.1.2 Name, Role, Value (Level A)
- 3.3.1 Error Identification (Level A)
- 4.1.3 Status Messages (Level AA)
hi!
Thanks for the detailed report! We are looking into these issues
Where have you seen this behavior? "The aria-errormessage attribute does not match the ID of the error message container"
I could not reproduce this with aSelect or SimpleSelect, e.g.
<SimpleSelect renderLabel="Uncontrolled Select"
messages={[{type: 'newError', text: 'Password have to be at least 6 characters long!'}]}>
<SimpleSelect.Option id="foo" value="foo"
renderBeforeLabel={(props) => {
console.log(props)
return <IconCheckSolid />
}}>
Foo
</SimpleSelect.Option>
<SimpleSelect.Option id="bar" value="bar">
Bar
</SimpleSelect.Option>
<SimpleSelect.Option id="baz" value="baz">
Baz
</SimpleSelect.Option>
</SimpleSelect>
afaik we are only using aria-errormessage with RadioInputGroup at the moment
Also about aria-errormessage: I've tried adding it to our TextInput component's first example,
VoiceOver reads Password Password have to be at least 6 characters long! invalid data, secure edit text
NVDA reads then edit protected invalid entry Password have to be at least 6 characters long!
JAWS: Password Password has to be at least 6 characters long! password edit, invalid entry
Without it:
VoiceOver: Password Password have to be at least 6 characters long! invalid data, secure edit text (same)
NVDA: Password Password have to be at least 6 characters long! edit protected invalid entry
JAWS: Password Password has to be at least 6 characters long! password edit, invalid entry (same)
Is there some case where screenreaders perform better if we add this attribute? Thanks!
Hi,
Thanks for getting back to me - to answer your questions:
WRT "The aria-errormessage attribute does not match the ID of the error message container" - aria-errormessage isn't present at all on these components (Select & SimpleSelect), but aria-invalid is - it's my understanding that any error messages associated with the invalid input should be linked programmatically (e.g. aria-errormessage on SimpleSelect should be the id of Password have to be at least 6 characters long!). (this is a "may" rather than "must in WAI-ARIA 1.1 specification.)
The presence of aria-errormessage onFormFieldLayout led me to believe it should be being propogated down to Select (but that might not be the case).
As to the screenreader, the issue we're having not that the screenreader doesn't read messages, but that it doesn't announce them when the messages are rendered - the user would have to navigate back to that element to find that it was marked as invalid (see this simplified example https://stackblitz.com/edit/vitejs-vite-jgbvpolx?file=src%2FApp.jsx).
OK, so as I see you would like that form errors are read as soon as a component enters the error state (even when the page was just rendered and the component with the error state is offscreen?). We will investigate how tricky is to add this, and if we add it, it will be very likely not a default behaviour, rather some prop that toggles this mode.