useFocusZone

Designates a container where focus can be moved using keys other than 'Tab'.

This hook is useful for implementing many of the patterns described in Section 6 of the WAI-ARIA Authoring Practices document. The most common use case of this behavior is to allow arrow keys (up and down or left and right) to move focus between related elements, such as items in a menu.

At a high level, useFocusZone works by adjusting the tabindex attribute on focusable elements and setting up event listeners on the container that respond to the relevant key presses.

Focusability: which elements participate in the Focus Zone?

Focusable elements are those that either are normally focusable via the Tab key OR have a valid tabindex attribute (including "-1"). The easiest way to ensure an element participates in the focus zone is by applying the attribute tabindex="-1".

Entering the focus zone

By default, when focus enters a focus zone, the element that receives focus will be the most recently-focused element within that focus zone. If no element had previously been focused, or if that previously-focused element was removed, focus will revert to the first focusable element within the focus zone, regardless of the direction of focus movement.

Using the focusInStrategy option, you can change this behavior.

For more information on choosing the right focus in behavior, see 6.6 Keyboard Navigation Inside Components from the ARIA Authoring Practices document.

DOM focus vs. active descendant

The useFocusZone hook supports two modes of operation: DOM Focus and Active descendant.

  • DOM Focus is the default mode and by far the most commonly needed. When a key is used to move focus, we call .focus() directly on the element to receive focus. This results in document.activeElement getting set to this new element, and it will receive any necessary styles via :focus and :focus-within.
  • Active descendant mode does not move DOM focus. Instead, focus remains on the control element, and its aria-activedescendant attribute is set to the ID of the relevant element. Because there are no :focus styles applied and no focus events fired, you can supply an onActivedescendantChanged callback to handle any necessary styles or other logic as the active descendant changes. For more information on the Active descendant focus pattern, see 6.6.2 Managing Focus in Composites Using aria-activedescendant from the ARIA Authoring Practices document.

Examples

Default

Focus can be moved with up and down arrow keys in here.

Custom key bindings

The bindKeys option is used to set which of the following keys can be used to move focus.

This example shows how to use the bindKeys option to allow focus to be moved using the J and K keys.

Focus can be moved with J and K keys.

Custom first focused element

Setting focusInStrategy to "closest" will cause either the first or last focusable element in the container to be focused depending on the direction of focus movement. For example, a shift+tab that brings focus to the container will cause the last focusable element to be focused, whereas a regular tab would cause the first focusable element to be focused.

Otherwise, you may provide a callback to choose a custom element to receive initial focus. One scenario where this would be useful is if you wanted to focus an item that is "selected" in a list.

focusInStrategy: closest

Focus can be moved with up and down arrow keys in here.

"First" will be focused first when focus enters from "Before zone". "Third" will be focused first when focus enters from "After zone".

focusInStrategy: first

Focus can be moved with up and down arrow keys in here.

"First" will always be focused first when focus enters.

focusInStrategy: previous

Focus can be moved with up and down arrow keys in here.

The most recently focused element will be focused first when focus enters.

Custom focus out behavior

Focus cannot be moved beyond the last element of the container (other than using the Tab key). The focusOutBehavior option can be used to allow focus to wrap around from last to first element (or vice-versa).

For a more customized focus movement behavior, the consumer has the ability to supply a custom callback that identifies the next element to focus.

focusInStrategy: stop

Focus can be moved with up and down arrow keys in here.
Focus movement stops at the beginning and end.

focusInStrategy: wrap

Focus can be moved with up and down arrow keys in here.
Focus movement will wrap back around to the first or last element after reaching the beginning or end.

Custom focus movement

Focus can be moved in rows with left and right arrow keys. Focus can be moved in columns with the up and down arrow keys.

Prevent element(s) from being focused

If you need to prevent a focusable element from participating in the focus zone, you can provide a focusableElementFilter.

Focus can be moved with up and down arrow keys in here, but links will be skipped unless using the Tab key.

Link oneLink two

Prevent container from scrolling while moving focus

Focus can be moved with up and down arrow keys in here, and the container will not scroll when focus moves.

Disabling the focus zone

When the focus zone is enabled, focus can be moved with up and down arrow keys in here.

Active descendant behavior

This is the kind of behavior that comboboxes use, where the focus is on the control element, but the active descendant is set to the ID of the relevant element.

The active descendant can be moved in here while the controlling element is focused.

Nested focus zones

Focus can be moved with arrow up and arrow down keys in here.

Focus can be moved with up, down, left, or right arrow keys in here.

API

Loading data for useFocusZone...