🚀 feat(Input): add a11y attributes to Input #634
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Description 📄
This PR adds some accessibility improvements to the Input component, focusing mainly in improving the usability with screen readers:
a11yId
andincludeAriaAttributes
(more details about these below);aria-labelledby
to the input element, so that screen readers can announce the label of the input. If noa11yId
is provided,aria-label
is added instead (aria-labelledby
is preferable when there is a visible text that labels an element according to MDN);aria-describedby
to the input element, referencing the helper as it's description element. This allows the screen reader to announce helper and error messages associated with the input when the user focuses the input (works only if thea11yId
prop is provided).aria-live="polite"
to the Helper component, so that error messages can be announced by the screen reader as soon as they appear;aria-invalid
to the input element, setting it's value totrue
when theerror
prop has a truthy value. This allows the screen reader to announce that the input has invalid data.Generating HTML IDs for a11y
In order to use
aria-labelledby
andaria-describedby
on the input element, HTML IDs had to be added to the label and helper elements. Some approaches were considered in order to do this (thanks @caiotracera for giving some ideas here):useRef
oruseState
, and use it as a prefix for the HTML IDs. The pro of this approach is thataria-labelledby
andaria-describedby
would automatically work on all inputs without the need of passing a prop for that. The con is that some inconsistencies might happen with server side rendering (I honestly don't have experience with SSR and would like to know your opinions on this).aria-labelledby
andaria-describedby
working, it at least makes it possible to do it somehow. Another downside of this approach is that making the ID prop (a11yId
) optional made the code a bit hard to read due to, for example, conditional props passing.More about this can be found in this SO question and in this React issue.
New
includeAriaAttributes
propBesides the new
a11yId
prop, this PR also adds another prop to the Input component:includeAriaAttributes
. This prop has atrue
value by default and was added to give the possibility of including or not ARIA attributes on the Input, depending on the situation.The need for this prop arose from components that extend the Input component and have their own ARIA implementations, like Dropdown and AutoComplete (by the way, the usability of these two components with screen readers also need to be revisited in the future, even though they have the ARIA attributes added by downshift).
Platforms 📲
Type of change 🔍
How Has This Been Tested? 🧪
Open the Input page in the documentation app;
Start running a screen reader (on mac, press cmd+F5 to start VoiceOver);
Focus the input element:
aria-label
, since noa11yId
has being passed yet);Press the
< >
button in order to edit the code;Edit the code adding
error={value == "error" && "Error message"}
to the list of props being passed to theInput
component;Focus the input and type the word "error":
aria-live
);Focus any other element and then focus the input element again (still in the error state):
aria-invalid
). Although, in this case it's not expected to have the error description announced, since there's no link between the helper and the input yet;Edit the code once again, now adding
a11yId="id"
to the list of props being passed to theInput
component;Focus the input element:
aria-describedby
, that could be added because of thea11yId
;Edit the code one last time, adding now
includeAriaAttributes={false}
to the list of props being passed to theInput
component (feel free to keep the other added props or remove them);Focus the input element:
aria-label
/aria-labelledby
.Unit Test
Snapshot Test
Checklist: 🔍
Screenshots 📸
The videos below do not have audio, but the announcements of VoiceOver are shown as text in the gray box.
Before:
Screen.Recording.2023-03-22.at.09.43.21.mov
After:
Screen.Recording.2023-03-22.at.09.22.28.mov
a11yId
is passed)aria-live
, or everytime the input is focused when ana11yId
is provided