nirKa
nirKa

Reputation: 213

Angular 2+ navigation with mat-tab-nav-bar - accessibility

Angular material gives us in-app navigation with tabs.

By Angular:

<nav mat-tab-nav-bar> provides a tab-like UI for navigating between routes.

I want to make it more accessibile.

What we have now:

  1. Navigation with arrows (leftrightupdown) throw the list items.

  2. Enter activate the selected tab.

  3. Tab focus on the elements in DOM as usual (not update the selection as the arrow keys, details below).

Accessibility requirements:

  1. Tab will focus on the active tab (not necessary the focused tab).
  2. Shift+Tab on the nav list will jump to previous element in the DOM, befor the nav item. On the content page of the router Shift+Tab will jump from the first focusable element to the previous active element in the nav.
  3. Space should activate the selected tab like mouse click and Enter press.
  4. The elements in the nav (a elements) will be with the right aria roles.

I don't want to change the structure, just add it the accessibility that expected from tabs.

Any help please? How can I achieve the focus on the content from the nav in the correct way with the Tab and Shift+Tab keys?

Looking for correct structure.


More Details:

The mat-tab-nav-bar and mat-tab-link directive of angular for navigation are provide only a 'like' tabs UI. I want to enable in-app routing navigation by <router-outlet></router-outlet> directive element with keyboard accessibility.

From accessibility aspect I would expect navigate through the links with arrow keys, Enter activate the selected tab and Tab key will move the focus to the content of the routed page.

Because I want to update the URL when the user chage tabs I used the nav element with angular mat-tab-nav-bar directive, like in the example below:

<nav mat-tab-nav-bar>
  <a mat-tab-link
  *ngFor="let vehicle of vehicles; let i = index" 
    routerLink="{{vehicle}}"
            routerLinkActive="active"
    (click)="activeLink = vehicle"
    [active]="activeLink == vehicle">
    {{vehicle}}
  </a>
</nav>
<router-outlet></router-outlet>

In a 'real' nav and a element you can navigate with keyboard only by Tab, but not with arrow keys. But with the mat-tab-nav-bar directive the routing throw the tabs work indeed by arrows, but the Tab is not disabled for the a element.

I want to enable the tab key move to the content of the selected tab. I thought about angular FocusMonitor, or KeyManager to solve this situation, but couldn't achieve the desired result. I can also auto capture the focus to the selected tab content, but again it's not exactly the behavior of tabs.

For example, in this demo I want to navigate the tabs "Cars", "Airplanes" and "Bikes" with the arrow keys. When tab selected (with Enter or mouse) the Tab key will navigate to the input filed in the content. Currently what I achieved is just focus on the input when one tab selected (as shown in the "Bikes" tab). But I want to navigate like real tabs.

BTW, If you navigate throw the tabs with Tab on the mat-tab-nav-bar directive you will see the focus move from tab to tab, and press on enter will fire the click event on the a element. But if you press on the arrow keys to navigate throw the tabs, the focus will jump to the last active tab. simple reproduce: navigate with Tab key twice and press on the right-arrow key. you'll see the focus 'jumped' one step backward.

Here you can see the difference (examples from the official site):

'Real' tabs: press on tab will enter to the content of the tab.

'Like' tabs: press on tab will just move on throw the elements in the DOM.

Thanks!

Upvotes: 3

Views: 4064

Answers (1)

nirKa
nirKa

Reputation: 213

I found a great solution for the main question - the Tab/shift+Tab issue.

Simple directive do the work.

@Directive({
  selector: '[mat-tab-link]',
  host: {
      '[attr.tabindex]': 'getTabIndex',
  }
})
export class AccessibleTabNavDirective {

  constructor(private tabLink: MatTabLink) { }

  get getTabIndex() {
    return this.tabLink.active ? 0 : -1;
  }
}

Please note that in one case it's lackey. If one tab selected and previous tab focused the next tab will focus on the selected tab. For example: select the second tab and return to the previous tab (with Left-arrow) - the next Tab press will focus on the active tab and not on the page content.

But this issue happens in the 'real' angular tabs so I left it as is for now.

If you have a pretty solution for the Space too... you are welcome to comment.

Upvotes: 0

Related Questions