-
Notifications
You must be signed in to change notification settings - Fork 130
chore(treeview): add treeitem role to shadow dom node #3894
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
base: main
Are you sure you want to change the base?
Conversation
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR attempts to fix an accessibility audit issue by adding role="treeitem" to the tree-view-include-fragment custom element in the spinner loader component. However, this creates an invalid ARIA tree structure.
Changes:
- Added
role="treeitem"attribute to thetree-view-include-fragmentelement inspinner_loader.html.erb
Comments suppressed due to low confidence (1)
app/components/primer/alpha/tree_view/spinner_loader.html.erb:5
- The
skeleton_loader.html.erbfile does not haverole="treeitem"on itstree-view-include-fragmentelement (line 5), creating an inconsistency with the spinner_loader change. This inconsistency suggests that adding the role to spinner_loader may not be the correct approach. Both loaders should be treated the same way since they serve the same purpose and have the same DOM structure.
<%= render(Primer::BaseComponent.new(tag: :"tree-view-include-fragment", src: @src, loading: :lazy, data: { target: "tree-view-sub-tree-node.subTree tree-view-sub-tree-node.includeFragment", path: @container.path.to_json }, hidden: @container.expanded?, accept: "text/fragment+html", role: "treeitem")) do %>
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| <% end %> | ||
|
|
||
| <%= render(Primer::BaseComponent.new(tag: :"tree-view-include-fragment", src: @src, loading: :lazy, data: { target: "tree-view-sub-tree-node.subTree tree-view-sub-tree-node.includeFragment", path: @container.path.to_json }, hidden: @container.expanded?, accept: "text/fragment+html")) do %> | ||
| <%= render(Primer::BaseComponent.new(tag: :"tree-view-include-fragment", src: @src, loading: :lazy, data: { target: "tree-view-sub-tree-node.subTree tree-view-sub-tree-node.includeFragment", path: @container.path.to_json }, hidden: @container.expanded?, accept: "text/fragment+html", role: "treeitem")) do %> |
Copilot
AI
Jan 28, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adding role="treeitem" to the tree-view-include-fragment element creates an invalid ARIA tree structure. According to the WAI-ARIA specification, a treeitem element cannot contain a group element, but this tree-view-include-fragment wraps a ul[role="group"] (SubTreeContainer).
The actual DOM structure becomes:
li[role="none"]
└── tree-view-include-fragment[role="treeitem"] ← Invalid
└── ul[role="group"]
└── li[role="none"]
└── div[role="treeitem"]
The tree-view-include-fragment is a technical implementation detail for lazy loading and should remain role-less (allowing it to be transparent in the accessibility tree). The actual treeitems are the div[role="treeitem"] elements inside the ul[role="group"] that this fragment contains.
Note that skeleton_loader.html.erb does not have this role attribute, creating an inconsistency. The correct fix depends on what the actual accessibility issue is. If the concern is that the loading indicator needs to be announced, the role should be on the inner Node element (which already has role="treeitem" from Node.rb line 108), not on the outer include-fragment wrapper.
| <%= render(Primer::BaseComponent.new(tag: :"tree-view-include-fragment", src: @src, loading: :lazy, data: { target: "tree-view-sub-tree-node.subTree tree-view-sub-tree-node.includeFragment", path: @container.path.to_json }, hidden: @container.expanded?, accept: "text/fragment+html", role: "treeitem")) do %> | |
| <%= render(Primer::BaseComponent.new(tag: :"tree-view-include-fragment", src: @src, loading: :lazy, data: { target: "tree-view-sub-tree-node.subTree tree-view-sub-tree-node.includeFragment", path: @container.path.to_json }, hidden: @container.expanded?, accept: "text/fragment+html")) do %> |
…onents into chore/add-treeview-role
Authors: Please fill out this form carefully and completely.
Reviewers: By approving this Pull Request you are approving the code change, as well as its deployment and mitigation plans.
Please read this description carefully. If you feel there is anything unclear or missing, please ask for updates.
What are you trying to accomplish?
Resolve accessibility audit issue where child role is missing
Screenshots
Integration
N/A
List the issues that this change affects.
Closes https://github.com/github/accessibility-audits/issues/14650
Risk Assessment
What approach did you choose and why?
Consulted a11y on the best fix and decided to add
role="treeitem"to the shadow dom node to solve the a11y scan issue, though this may not translate to a real world scenario in this case.Anything you want to highlight for special attention from reviewers?
N/A
Accessibility
Merge checklist
Take a look at the What we look for in reviews section of the contributing guidelines for more information on how we review PRs.