0

Lets say I have an element with role="tree". Under that I have an element role="group" which contains elements with role="treeitem" or role="group" for multilevel tree.

<... role="tree">
    <... role="group">
        <... role="treeitem">
        <... role="treeitem">
        <... role="group">
            <... role="treeitem">
            <... role="treeitem">

The issue here is that that the accessibility test tool is complaining that the element with role="tree" must contain a child element with role="treeitem".

Looked up the spec and it says

Required Owned Elements:    
        group → treeitem
        treeitem

How do I interpret this? Should a tree contain a treeitem directly? could tree have a group which contains tree items but the tree has no direct children with role "treeitem"?

-- EDIT--

Here is the complete html

<!DOCTYPE html>
<html lang="en">
    <head>
        <title>Test Tree A11y</title>
    </head>
    <body>
        <div role="main">
            <!-- tree contains a group which contains treeitems/group -> treeitems -->
            <ul role="tree">
                <ul role="group">
                    <li role="treeitem">Banana</li>
                    <li role="treeitem">Mango</li>
                    <ul role="group">
                        <li role="treeitem">Banana-2</li>
                        <li role="treeitem">Mango-2</li>
                        <li role="treeitem">Orange-2</li>                    
                    </ul>
                </ul>
            </ul>

            <!-- tree contains a treeitems or groups which contains treeitem -->            
            <ul role="tree">
                <li role="treeitem">Banana</li>
                <li role="treeitem">Mango</li>
                <ul role="group">
                    <li role="treeitem">Banana-2</li>
                    <li role="treeitem">Mango-2</li>
                    <li role="treeitem">Orange-2</li>                    
                </ul>
            </ul>
        </div>
    </body>
</html>

The question here is

Should an element with a role "tree" must contain one or more "treeitems"? Can it contain a "group" which contains "treeitems?"

In the first tree

  • Tree has a group, no direct children of role treeitem
  • The group has tree items and a group which has other tree items This is reported as an error WCAG 1.3.1. However, the screen readers seem to be working fine

In the second tree

  • Tree has a tree items and a group which has other tree items

In the spec, I am not able to find a definite statement that tree must conatin 1 or more DIRECT children with a role treeitem. So I am not certain that the first tree has an actual accessibility issue and if the first tree is violating the spec.

FWIW, there is a control called JSTree which is using the style as shown in first tree, and I am debating if that is a real issue or not. Thanks.

dgorti
  • 1,130
  • 2
  • 12
  • 22
  • Could you add your actual HTML rather than pseudo HTML as without seeing how you are structuring this properly it is hard to give pointers. There must be at least one `treeitem` but it can have a sibling that is a `group` that it controls which is why `group` is a valid descendent of a `tree`. If you could give us an HTML example that you think should work but fails the validator we can explain better. – GrahamTheDev Feb 06 '21 at 09:02
  • @GrahamRitchie, Thank you. I edited the post and added more details. Thank you for your response – dgorti Feb 06 '21 at 20:24

2 Answers2

3

Short Answer

Although it is valid HTML and WAI-ARIA to have a group as the direct descendant of a tree it is not the intended or recommended use if it not associated with a corresponding treeitem.

It is an allowed child of role="tree" due to different ways a tree can be constructed.

Long Answer

Firstly it is perfectly "valid" (it is valid markup) to have a role="group" as the only descendant of a role="tree".

However although valid it is not the recommended way of doing things and may result in unexpected behaviour depending on the screen reader and browser combination in use.

The key point is that in the WAI-ARIA best practices document it states that:

Each root node is contained in the element with role tree or referenced by an aria-owns property set on the tree element.

So the second you put the top level nodes into a role="group" you break this rule unless you give each of the treeitems in your group an id and then use aria-owns on the role="tree". At which point the group becomes pointless anyway as you have bypassed it.

So why allow a role="group" as a descendant of role="tree" if it is not recommended?

Now you could argue that if it wasn't valid to have a group as a top-level item in a role="tree" that it shouldn't be allowed in the first place.

However, the reason that role="group" is allowed at the top level is that you can set a treeitem to open a group and these can be on the same level (siblings).

I think I can explain this best with an example:-

Code Example 1 - valid as the group has a parent treeitem and so does not act as a root node.

<div id="tree1" role="tree" tabindex="-1">
  <div role="treeitem" aria-owns="pizzaGroup" aria-expanded="false" tabindex="0">Pizza Toppings</div>
  <ul role="group" id="pizzaGroup">
      <li role="treeitem">Cheese</li>
      <li role="treeitem">Pepperoni</li>
      <li role="treeitem">Onion</li>
   </ul>
</div>

In the example above the first div acts as the treeitem and the group is controlled by it. The association is made with aria-owns.

The reason it states that it must contain group -> treeitem is because an empty group is not allowed.

The above is a valid example of a role="tree", however I would not recommend that pattern if you can avoid it as support for aria-owns is not great.

The accepted practice is to have the group nested within the treeitem itself and to use <ul> and <li> throughout. Most screen readers will automatically associate the child nodes with the parent node and those that don't still have a way for their users to workout the relationship as nested <ul> and <li> are well supported.

Example 2 - an example of the recommended pattern using <ul> and <li>

<ul role="tree">
    <li role="treeitem" aria-expanded="false" tabindex="0">
    <span>Pizza Toppings</span>
        <ul role="group">
            <li role="treeitem">Cheese</li>
            <li role="treeitem">Pepperoni</li>
            <li role="treeitem">Onion</li>
        </ul>
    </li>
</ul>

Hopefully that answers why the accessibility tool was complaining about not having a treeitem and why you can have a group as a child of a tree but only if it is controlled by an associated treeitem.

Final Thoughts

In your example you haven't provided a label for your tree. Don't forget to add a label to the main element eith role="tree", either a visible label and aria-labelledby="yourLabelID" (preferable) or with an aria-label="description of tree".

Update after discussions in chat

If only guidance was more clear!

As pointed out my supporting information for a "root node" is still not clear and it is fair to comment it could still interpreted that a group can be a root node from that definition.

However further up in the definition of a treeview, coupled with another of the rules, there is enough clarity to confirm that it is in fact impossible for a group to be counted as a root node at all!

These are the definitions of nodes in a tree:

Node An item in a tree.

Root Node Node at the base of the tree; it may have one or more child nodes but does not have a parent node.

Child Node Node that has a parent; any node that is not a root node is a child node.

Parent Node Node with one or more child nodes. It can be open (expanded) or closed (collapsed).

Take the following rule:

Each child node is contained in or owned by an element with role group that is contained in or owned by the node that serves as the parent of that child.

You therefore cannot count a group as a root node (or any node) under any circumstances, it cannot have a parent and so contravenes the above rule.

Let me explain why this is the case and why you can never treat a group as a root node:

The second you add a treeitem to a group the following must be true:

  • it must be a child node as it is not a root node.
  • each child node must be contained or owned by a role="group" that must be contained or owned by a node that serves as the parent of the newly added treeitem.
  • A root item can have no parent node and our group requires a parent to be valid.

Example 3 - not valid as the group has no parent node and would have to act as a root node (which it cannot).

<div role="tree">
     <!--this group is a root level node and does not have a parent node. -->
     <div role="group">
         <!--This treeitem must be within a "group" as it is a child node. -->
         <!--This means that the "group" above contains it and that means the group above must be owned or controlled by something.-->
         <!--This treeitem can never have a parent as root level nodes cannot have a parent node.-->
         <div role="treeitem">item</div>

     </div>
 </div>

Also the following takes all of the ambiguity away as far as I am concerned:

Each element serving as a tree node has role treeitem.

So my original premise was correct for why a group is allowed as a top level item in a tree.

In fact it is even more clear, a group can never be a root node (or a node at all as you cant have role="treeitem group"!) and the only reason a group can appear as a direct descendant of a tree is if it is a sibling with a treeitem that controls it (it's parent) as I originally said.

GrahamTheDev
  • 22,724
  • 2
  • 32
  • 64
  • Not a problem at all, here to help! – GrahamTheDev Feb 07 '21 at 02:37
  • 1
    Sorry but you misread the notion of "root node". A root node can be of role `treeitem` or `group`. A root node is defined as being "Node at the base of the tree", nothing else. The `aria-owns` is used when a node is outside the role `tree` DOM element (see note in the same paragraph) – Adam Feb 07 '21 at 06:17
  • Updated my answer to include additional information. I can understand why you might think that from the example I gave, hopefully the above confirms it more clearly that a `group` cannot be a `root node`. – GrahamTheDev Feb 07 '21 at 12:27
  • @GrahamRitchie, this feels like I am back to square one, I am sure I am missing something. Lets me state this again to see if I can make it more clear. 1. I am completely aligned with why a "root node" can't be a group. RootNode, has a role of "tree" anyway. 2. In your example, the root node has no direct children of role "treeItem". The direct child is an element with a role "group" from DOM tree perpsective. 3. The only child div of the root node (DOM perspective) is a group, which as elements with role "tree Item". Am I interpreting that the first tree in my example is valid? – dgorti Feb 07 '21 at 18:48
  • A "root node" is not the tree itself, it is a node one level down "Each root node is contained in the element with role tree or referenced by an aria-owns property set on the tree element." Honestly they make it so complicated for no reason, why can't they just say "tree" "first level node directly under tree" etc. We wouldn't have so much confusion then. Long story short, `treeitems` are the only valid first level items under `tree` if you follow the second and recommended pattern of nesting an `
      ` within a `
    • `. The fact we are all having to debate this shows how poorly explained it is!
    – GrahamTheDev Feb 07 '21 at 18:56
  • [exceeded the comment length - continuing here] Your example results in an error in AccessibilityInsights tool, with WCAG 1.3.1 error. – dgorti Feb 07 '21 at 18:56
  • @GrahamRitchie, am I interpreting this correctly that your DIV example is an incorrect pattern?
    item
    – dgorti Feb 07 '21 at 19:04
  • Which example throws an error? The first one with a div is a valid pattern although not advised. The group does not act as a node as it is owned by the `treeitem` above it. That was the main thing I was trying to say was why the spec says you can have a group directly under the `tree` but only if it is owned (via `aria-owns`) by a `treeitem`. – GrahamTheDev Feb 07 '21 at 19:12
  • 1
    Are you talking about the last example as that one is meant to show why a group cannot be a top level item if it is not owned by another. The last example in my update is indeed invalid if you mean that one? – GrahamTheDev Feb 07 '21 at 19:14
  • I have numbered the examples to make this easier. – GrahamTheDev Feb 07 '21 at 19:17
  • The error being thrown isn't you testing example 1 and the accessibility checker complaining about the lack of a label by any chance is it? A `tree` must have either an `aria-label` or be labelled by another element with `aria-labelledby`, which I did say you needed to do in the final thoughts section. – GrahamTheDev Feb 07 '21 at 19:20
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/228381/discussion-between-dgorti-and-graham-ritchie). – dgorti Feb 07 '21 at 19:23
0
Required Owned Elements:    
        group → treeitem
        treeitem

The documentation of treeitem will help you understand this subject

Authors MUST ensure elements with role treeitem are contained in, or owned by, an element with the role group or tree.

This means that leaves of a tree item must all be treeitem.

Those treeitem can be directly under the tree item or any level of group items.

You can't have a treeitem under a treeitem

Adam
  • 17,838
  • 32
  • 54
  • Thank you, but thats not the question – dgorti Feb 06 '21 at 19:56
  • Your comment is quite rude. Your questions are *"Should a tree contain a treeitem directly? could tree have a group which contains tree items but the tree has no direct children with role "treeitem"?"*. The answer is "Those treeitem can be directly under the tree item or any level of group items.". This means "Not necessarily" for the first one, and Yes for the second one (with any level of group items) – Adam Feb 06 '21 at 20:05
  • I did not mean to be rude. Thank you for your comments. Perhaps I did not describe my question properly. The question is not about the rules of treeitems. The question is about whether a tree MUST contain one ore more treeitems as children. Can it contain a single group which has treeitems? Thanks again – dgorti Feb 06 '21 at 20:27
  • To be simple : your example is totally valid. It would be less controversial with two groups (because having one group has not much interest), but I guess your tool would still report the error while it should not. – Adam Feb 06 '21 at 20:59
  • It seems there are different interpretations and the spec is not clear. I could see the argument that a tree must contain 1+ tree items and 0+ groups. In that case you will have a group only if you have 2nd level treeitems. It would be nice to see a definitive statement from the spec so I can decide weather it is a bug in my code or the accessibility checker – dgorti Feb 06 '21 at 21:16
  • The specs are clear. Definitely a bug within the accessibility checker. – Adam Feb 07 '21 at 06:18