I am trying to solve the accessibility issue discovered by axe tools for tablist.
In our case tabs in a tablist are separated by the vertical separator with an appropriate role and aria-orientation. However the tool says that role=separator is not allowed to be inside of element with role=tablist.
Ensures elements with an ARIA role that require child roles contain them
The code looks as following:
<div role="tablist" aria-orientation="horizontal">
<button id="tab-0" aria-controls="panel-0" type="button" role="tab" tabindex="0" aria-selected="true">One</button>
<div class="vertical-separator">
<div class="tab-separator role="separator" aria-orientation="vertical"></div>
</div>
<button id="tab-1" aria-controls="panel-1" type="button" role="tab" tabindex="-1" aria-selected="false">Disabled</button>
</div>
What is a way to satisfy the accessibility rule? As a tool's proposal there are two ways:
Element has children which are not allowed (see related nodes)
Element has no aria-busy="true" attribute
But none of them is fitting
If you want to nit-pick, one could argue that axe is wrong with that error.
The tablist role says that "Required Owned Elements" must have a role of tab. It does not really say that only tab roles can be children.
For example, the spec for
<ul>says:That is, it specifically says that child elements of a
<ul>must only be<li>elements (or scripting elements).The "Required Owned Elements" section of roles is not as specific. It does not say that only certain child elements are allowed but rather, in order for a child element to be considered owned by the parent, it must have a specific role.
In this case, in order for a child element to be owned by the
tablist, it must have a role oftab. If a child element does not have that role, then it's not considered owned by the tablist. Does that mean a tablist cannot have child elements without a tab role? That's where it gets iffy. It doesn't really say that although I'm sure it's a good idea.Even the URL for "Required Owned Elements" is called "#mustContain". Meaning, it must contain a tab child. But the URL is not called "#mustOnlyContain".
The tablist pattern says:
Again, this doesn't say that all child elements must be a tab, but only those child elements with a role of tab will be considered a tab and owned by the tablist.
When a tablist is surfaced to assistive technology, such as a screen reader, it will look at all the child elements of the tablist that have a role of tab and that will be the count of the number of tabs. The screen reader will say "[tab label], tab, 3 of 4". Any child that does not have a role of tab will not be included in that count.
Now, with all that being said, I would still encourage that all child elements have a role of tab, but I'm not sure it really breaks the rules if you don't.
In your particular case, it might be better to use CSS :after on the tab button to add a vertical separator rather than the separator being a separate DOM element.
The tablist example in the design pattern has a gap between each tab button. That gap is done with CSS on the button rather than a separate gap DOM element.