Adding accessibility support

Accessibility is very important when it comes to the components library. Our components need to be accessible to all users. Some users may be blind, use screen readers to access our websites, or have a motor disability, which means they can only use the keyboard to access the website. 

If you are using Windows, you can use tools such as NVDA to run a screen reader on your machine. If you are using a macOS, then you can use VoiceOver, which is built into macOS. 

We've already added aria-popup to our DirectiveToggleDirective. However, we also need to set the aria-controls attribute, which tells the screen reader what element the popup is, which is controlled by this toggle. In our HTML, we have aria-controls set to dropdown-menu, which is the ID on the drop-down menu element. When we have multiple drop-downs, these IDs need to be different for each element.

Let's use uniqueId from Lodash to produce a new unique ID for our DropdownMenu. We will be using HostBinding and the following code:

import { Directive, Host, HostBinding } from '@angular/core';
import uniqueId from 'lodash-es/uniqueId';

...
export class DropdownMenuDirective implements AfterContentInit {
@HostBinding('id') id = uniqueId('dropdown-id-');
...
}

Now, let's access id so that we can set aria-controls on our DropdownToggleDirective. We do this by accessing the id we just created in DropdownMenu, like so:

import { Directive, Host, ElementRef, HostBinding } from '@angular/core';

...
export class DropdownToggleDirective {
...

@HostBinding('attr.aria-controls') get ariaControls() {
return this.dropdown.menu.id;
}
}

Now, when we have multiple drop-downs on our page, this will make sure that each drop-down has a unique ID for accessibility.

Next, let's work on the keyboard accessibility of our component. When you use Tab to go to our Dropdown button element and click Enter or space, you should see that the drop-down opens up. However, there is no way for us to select the items from the menu using the keyboard alone. We want to use the up and down keyboard keys to traverse the menu. When we click Enter, we want the focus to go back to Dropdown button.

We will be using Angular CDK's focus manager to manage the focus of our drop-down. Let's start by adding the focus method to our DropdownItemDirective, which will focus on nativeElement of the host element:

...
export class DropdownItemDirective {
...
constructor(private el: ElementRef) { }

focus() {
this.el.nativeElement.focus();
}
}

Now, we'll use ContentChildren in DropdownMenuDirective to access all of the DropdownItemDirective that are used inside it. Then, in the AfterContentInit life cycle method, we'll initialize our FocusKeyManager. We'll also add the keydown event and call the onKeydown method of keyManager.

Let's make these changes in DropdownMenuDirective, as follows:

import { Directive, Host, ContentChildren, QueryList, AfterContentInit } from '@angular/core';
...
import { DropdownItemDirective } from './dropdown-item.directive';

@Directive({
selector: '[baDropdownMenu]',
host: {
...

'(keydown)': 'onKeydown($event)'
}
})
export class DropdownMenuDirective implements AfterContentInit {
@ContentChildren(DropdownItemDirective) items:
QueryList<DropdownItemDirective>;
public keyManager: FocusKeyManager<DropdownItemDirective
>;

...


ngAfterContentInit() {
this.keyManager = new FocusKeyManager(this.items).withWrap();
}

onKeydown(event) {
this.keyManager.onKeydown(event);
}
...
}

Now, we need to make sure that, when the drop-down opens, the first item is selected in the menu. We do this by updating the _toggle method in DropdownToggleDirective, like so:

...
export
class DropdownToggleDirective {
...

_toggle(event) {
this.dropdown.open = !this.dropdown.open;
if (this.dropdown.open) {
setTimeout(() =>
this.dropdown.menu.keyManager
.setFocusOrigin('keyboard')
.setFirstItemActive()
);
}
}
}

Let's try demo once again. Now, you should be able to use the following code:

import { Directive, Host, ElementRef } from '@angular/core';
...

export
class DropdownToggleDirective {
...

constructor(
@Host() private dropdown: DropdownDirective,
public el: ElementRef
) {
this.dropdown.toggle = this;
}
}

Now that we have ElementRef el available on DropDownToggleDirective, let's use it in DropDownMenuDirective to focus on nativeElement, as follows:

...
import { ENTER } from '@angular/cdk/keycodes';
...
export class DropdownMenuDirective implements AfterContentInit {
...

onKeydown(event) {
if (event.keyCode === ENTER) {
this.dropdown.toggle.el.nativeElement.focus();
} else {

this.keyManager.onKeydown(event);
}
}
...
}

Now that we have our component ready to be used in our project, let's try to publish the library on npm so that anyone can consume it in their project.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.224.63.87