ControlWithError: Connect validation messages to controls via aria-describedby#76742
ControlWithError: Connect validation messages to controls via aria-describedby#76742
ControlWithError: Connect validation messages to controls via aria-describedby#76742Conversation
| // The `help` prop is rendered visually by BaseControl but is not | ||
| // programmatically associated with the combobox input via aria-describedby. | ||
| // This is a pre-existing bug in ComboboxControl, not caused by ControlWithError. |
| // The `help` prop is rendered visually by BaseControl but is not | ||
| // programmatically associated with the toggle group via aria-describedby. | ||
| // Additionally, the validity target is a hidden delegate radio input, not the | ||
| // toggle group itself. These are pre-existing bugs, not caused by ControlWithError. |
| required, | ||
| } ) } | ||
| <div aria-live="polite">{ showMessage && message() }</div> | ||
| <div aria-live="polite">{ visibleMessage }</div> |
There was a problem hiding this comment.
The original issue suggested replacing this live region with a11y.speak(), but this would require a substantial refactor. Let's leave it this way for now.
|
Flaky tests detected in 1738692. 🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/23367857806
|
|
Size Change: +130 B (0%) Total Size: 7.66 MB
ℹ️ View Unchanged
|
|
The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message. To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. |
What?
Closes #76694
Explicitly connect validation error messages to their respective form controls using
aria-describedby, so that screen reader users can access error messages when navigating back to a field.Why?
Validation errors were displayed visually and announced via
aria-live, but not programmatically associated with the input viaaria-describedby. The errors are tied to the element through the Constraint Validation API, but if a user missed the live announcement (e.g. due to distraction or another announcement overriding it), there was no way to discover the error by returning to the field.How?
ValidityIndicatoranidprop and apply it to its root<p>element.ControlWithError, generate a stablemessageIdviauseId()and pass it toValidityIndicator.aria-describedbyon the validity target element via auseEffect, merging themessageIdalongside any existingaria-describedbyvalues (e.g. from ahelpprop). In other words, we can't merge the attribute throughcloneElementbecause we can't know the internals of the cloned element and whether ahelpprop or something maps toaria-describedbyinternally.Known limitation
For controls that use a hidden element as a validation delegate (
ValidatedCustomSelectControl,ValidatedFormTokenField,ValidatedToggleGroupControl), thearia-describedbyis attached to the hidden delegate rather than the interactive control, making this fix rather useless. Tracked separately in #76741, and bumped from this PR because it doesn't affect shipping features in WP 7.0.Testing Instructions
Automated
New test coverage across 13 dedicated test files, one per validated control:
helpprop (CheckboxControl,TextControl,TextareaControl,InputControl,NumberControl,SelectControl,RadioControl,RangeControl,ToggleControl): tests that the help description is preserved and that the validation error is appended alongside it.helpwiring bugs (ComboboxControl,ToggleGroupControl): tests asserting correct behavior, skipped with comments explaining the pre-existing issue.FormTokenField,CustomSelectControl): tests that the interactive control's built-in description is not broken by validation.The
control-with-error.tsxtest file retains tests for corearia-describedbymechanism behavior: basic connection, rawaria-describedbyprop preservation,customValiditypath, and cleanup on error resolution.Manual
npm run storybook:devand navigate to theValidatedTextControlstory.requiredvia the controls panel).Use of AI Tools
Authored with Cursor (Claude).