-
Notifications
You must be signed in to change notification settings - Fork 6.8k
Description
Feature Description
I am using the Angular Material <mat-tree>
component for the (primary) site navigation menu in our web application. However, this creates problems regarding WCAG compliance and accessibility.
According to the ARIA Authoring Practices Guide (APG), tree structures can be used for page navigation as demonstrated in the Treeview Navigation Example. The guidelines specify that:
aria-current="page"
should be used (instead ofaria-selected
) to indicate the current page- Navigation should be implemented using
<a>
tags
Angular Material however enforces this default role structure:
mat-tree → role="tree"
mat-nested-tree-node → role="treeitem"
...there is an issue when trying to use semantically correct links (<a>
tags) within <mat-nested-tree-node>
– for example, with aria-current="page".
When we intend to use the <mat-tree>
component as a recursive tree-based site navigation, the question becomes how to correctly integrate and semantically mark up an <a>
tag. Ideally, the <a>
tag itself should receive the role="treeitem" and the aria-current="page" attribute when it represents the current page.
Currently, it's unclear to us how the <mat-tree>
component can be extended to meet this specific requirement for web links.
Removing the <a>
tag and replacing it with manual navigation (this.router.navigate()) is not an option due to synchronization problems etc.
The following code snippet shows our current approach:
<mat-tree [dataSource]="treeDataSource" [treeControl]="treeControl" class="nested-tree">
<mat-nested-tree-node [attr.aria-current]="linkActive.isActive ? 'page' : null"
*matTreeNodeDef="let item; when: hasChild">
<div
class="mat-tree-node"
matTreeNodeToggle
routerLinkActive="menu-nav--highlighted"
[routerLinkActiveOptions]="{ exact: true }"
#linkActive="routerLinkActive">
<button mat-mini-fab color="light" [attr.aria-label]="'toggle ' + item.title" tabindex="-1">
<mat-icon [svgIcon]="treeControl.isExpanded(item) ? 'arrow-down-20' : 'arrow-right-20'">
</mat-icon>
</button>
<a
class="menu-nav__link tree-node-link"
[routerLink]="item.route"
tabindex="-1"
[attr.aria-label]="item.title"
[attr.title]="item.title"
rel="noopener noreferrer"
(click)="onNodeToggle($event, item)">
{{ item.title }}
</a>
</div>
<div [ngClass]="{ hidden: !treeControl.isExpanded(item) }" role="group">
<ng-container matTreeNodeOutlet></ng-container>
</div>
</mat-nested-tree-node>
</mat-tree>
I would appreciate an official way or best practice to semantically implement accessible links with aria-current inside the mat-tree pattern.
Thank you in advance for any feedback or proposed solutions!
Use Case
A way to configure mat-tree so that:
- Links are correctly identified as treeitem
- aria-current="page" can be set for the current page
- Navigation works optimally both via keyboard and screen reader