Keyboard focus and navigation are essential when developing for the accessible web. Many users rely on a keyboard when they surf the web.

If a user doesn’t use other input mechanisms, they’ll have a tough time interacting and navigating your site unless it’s keyboard navigable.

In this article, we’ll learn how Angular CDK makes adding this ability easier.

We’ll create a searchable list and add the option to choose items using the keyboard. Here is a demo that illustrates our final result:

Let’s start by creating a list-item component:

This component is straightforward. It gets the item via input and displays the content via ng-content . Now, let’s move on and create the app component:

This is basic stuff. We loop over an array of users and display the username. Now we have a searchable list, so let’s add the keyboard interaction.

The ListKeyManager Class

ListKeyManager manages the active options in an item list based on keyboard interactions. It’s intended to be used with components that correspond to a role="menu” or role="listbox” pattern.

Any component that uses a ListKeyManager need to do three things:

Create a @ViewChildren query for the options being managed.

query for the options being managed. Initialize the ListKeyManager , passing in the options.

, passing in the options. Forward keyboard events from the managed component to the ListKeyManager .

There are two varieties of ListKeyManager , ActiveDescendantKeyManager and FocusKeyManager . Let’s start with ActiveDescendantKeyManager .

The ActiveDescendantKeyManager Class

We instantiate the ActiveDescendantKeyManager class, which extends the ListKeyManager class and passes on the query list to it.

We also call the withWrap() method, as we want to wrap to the other end of the list when there are no more items in a given direction (looping).

We listen for the input’s keydown event and pass the event to the onKeyDown() method of the keyManager object. Under the hood, active option will be managed based on the user’s keyboard navigation.

When the user presses enter, we can grab the active option via the activeItem property of the keyManager object.

Now, let’s see how to style the active option. Each managed item should implement the Highlightable interface:

As the user navigates, Angular calls the setActiveStyles() method on the newly active option and setInActiveStyles() on the previously option. This allows us to style our component.

The FocusKeyManager Class

The FocusKeyManager class is used when options receive direct browser focus. Each managed item must implement the FocusableOption interface:

As the user navigates, Angular calls the focus() method on the newly active option.

Tab Focus

Skipping Items

We have two options for skipping items during navigation. The first option is setting the item disabled property to true. For example:

The second option is to define a skipPredicate() method. For example:

Typehead Mode

We can turn on the typeahead mode. This allows users to set the active item by typing. That means that when the user searches, the first result is automatically set as active.

Let’s add the search functionality.