Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Accessibility: list in nested options #5915

Closed
meldafert opened this issue Aug 27, 2020 · 3 comments
Closed

Accessibility: list in nested options #5915

meldafert opened this issue Aug 27, 2020 · 3 comments

Comments

@meldafert
Copy link
Contributor

Hello,

When using nested options (<optgroup>), a <ul> item gets added to contain the options.
However, this does conform to WCAG, as the group inside of a listbox only may contain elements with an option role.

var $childrenContainer = $('<ul></ul>', {
'class': 'select2-results__options select2-results__options--nested'
});

This can be fixed by giving the <ul> a role='none', as then it is ignored.
I would be open to writing a PR to fix this.

@kevin-brown
Copy link
Member

The recommendations are fun on this aspect, because in ARIA 1.1 they did not have a concept of "groups" at all. This was only added in ARIA 1.2 after it was pointed out that <optgroup> could not be represented.

Per ARIA 1.2 docs on listbox role:

Items within the list are static and, unlike standard HTML select elements, may contain images. List boxes contain children whose role is option or elements whose role is group which in turn contains children whose role is option.

You have correctly identified that the children of a listbox role must have the role of option and that it can also contain elements with a role of group. By not saying that both roles must be children, and instead specifying that group must be contained within listbox, I interpreted this to allow for the gap that Select2 gives within the DOM hierarchy.

Unfortunately the example given for listbox with group roles does not mix group and option roles in the same DOM level. This is a common use case, only supported by the HTML <select> element with <option> and <optgroup> elements, but the example does not reflect this common use case. It also deviates from the other examples by having the listbox role on the enclosing <div> instead of the <ul> that other examples use, missing the opportunity to demonstrate how this would be done with standard list markup. The markup used within that example is not reflective of the way you would do nested lists with a mix of <ul> and <li> elements as well, which is what Select2 is based on.

This can be fixed by giving the <ul> a role='none', as then it is ignored.

It's not immediately clear why this is an acceptable fix, other than because it resets the default role on the <ul> (which I believe is list?).

@meldafert
Copy link
Contributor Author

This is indeed somewhat unclear in the specification, as you say. It requires that the option element "is owned by" the group element, while specifying that "owned" means that it is "any DOM descendant".
This would imply that indeed, an element with role='list' (the <ul>, in this case) may be between the group and option elements.
This is wrong, however, as this will trip up screen readers, incorrectly announcing the options or possibly not recognizing it as a listbox at all. This is something the ARIA Working Group is aware of, and presumably will be fixed in the spec in 1.3 - requiring that the option element must be a direct descendant of the group element.

Regarding role='none', as per the specification: (with some exceptions)

The following elements are not exposed via the accessibility API and user agents MUST NOT include them in the accessibility tree:
- Elements with none or presentation as the first role in the role attribute.

This means, that adding role='none' on the <ul> fulfills the above requirement, as the option element then is a direct descendant of the group element, as far as the accessibility tree is concerned.

To demonstrate, here is Firefox' accessibility tree without role='none':
(The text container can be ignored):
Screenshot_20200901_121337

And here with role='none' on the <ul>:
Screenshot_20200901_121236

@kevin-brown
Copy link
Member

kevin-brown commented Sep 5, 2020

The visual with the accessibility tree helped here (didn't realize that existed, but it makes sense). I've merged it in so it will be included in the upcoming 4.1.0 release.

Thanks a lot for the explanation and the PR!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants