carbon
carbon copied to clipboard
fix(select): ensure aria-activedescendant is always valid
make the Select List always part of the DOM, and hide it with CSS instead. This allows the component to ensure that the guids provided as IDs to the Option children are always stable, so that the aria-activedescendant attribute of the Select Textbox always refers to the ID of an existing element. Also make the aria-controls attribute of the textbox always present so that screenreaders can know the list of options available when focused on the textbox.
fix #5289
Proposed behaviour
The Select textbox should always have an aria-controls attribute that refers to an option list that is always in the DOM, and is hidden and shown with CSS - similar to the ARIA Working Practices example here https://www.w3.org/WAI/ARIA/apg/example-index/combobox/combobox-select-only.html
Further, the IDs of each Option element should be stable (assuming no changes to the available options), so that the aria-activedescendant attribute, which changes as focus is moved among options with the keyboard as well as when selection is made with the mouse, always holds the actual ID of an element that is in the DOM (even if hidden).
Current behaviour
The Select option list is removed from the DOM when closed, so that when selecting an option and closing the list, the aria-activedescendant is invalid, causing Axe to flag an error.
Further, even when reopening the select so that the options are in the DOM again, the IDs are newly randomly-generated guids so the existing aria-activedescendant is still not referring to an element that's present in the DOM.
Checklist
- [X] Commits follow our style guide
- [X] Related issues linked in commit messages if required
- [X] Screenshots are included in the PR if useful
- [X] All themes are supported if required
- [X] Unit tests added or updated if required
- [X] Cypress automation tests added or updated if required
- [X] Storybook added or updated if required
- [X] Translations added or updated (including creating or amending translation keys table in storybook) if required
- [X] Typescript
d.tsfile added or updated if required
QA
- [ ] Tested in CodeSandbox/storybook
- [ ] Add new Cypress test coverage if required
- [ ] Carbon implementation matches Design System/designs
- [ ] UI Tests GitHub check reviewed if required
Additional context
Testing instructions
Test Stories for each type of Select (Simple select, FilterableSelect, MultiSelect). Select an option, close the select, and run Axe devtools. Reopen the select (without choosing a new option) and run again. Ensure that no errors are flagged (or at least not one saying ARIA attribute values are invalid!)
Also test with screenreaders across all supported screenreader/browser combinations, to ensure the Selects are usable - or at least there are no issues introduced here which didn't exist before.
This pull request is automatically built and testable in CodeSandbox.
To see build info of the built libraries, click here or the icon next to each commit SHA.
Latest deployment of this branch, based on commit 44a408fcc68c165de77a5dadd322207676878115:
| Sandbox | Source |
|---|---|
| carbon-quickstart | Configuration |
| carbon-quickstart-typescript | Configuration |
| carbon-quickstart | PR |
Test summary
Run details
| Project | carbon |
| Status | Passed |
| Commit | 44a408fcc6 |
| Started | Sep 7, 2022 1:48 PM |
| Ended | Sep 7, 2022 1:54 PM |
| Duration | 06:17 💡 |
| OS | Linux Debian - 10.10 |
| Browser | Chrome 100 |
View run in Cypress Dashboard ➡️
This comment has been generated by cypress-bot as a result of this project's GitHub integration settings. You can manage this integration in this project's settings in the Cypress Dashboard
:tada: This PR is included in version 110.4.1 :tada:
The release is available on:
Your semantic-release bot :package::rocket: