Навигация по элементам

React Aria предоставляет мощный набор хуков для обеспечения доступности компонентов, включая управление фокусом, клавиатурную навигацию и взаимодействие с элементами пользовательского интерфейса. В основе лежит концепция правильного управления фокусом и семантических ролей, что позволяет создавать интерфейсы, удобные для всех пользователей, включая людей с ограниченными возможностями.


Управление фокусом

Фокус — это ключевой аспект навигации. React Aria предлагает хуки для отслеживания и управления фокусом:

  • useFocusRing — позволяет определить, активен ли фокус на элементе, и предоставляет стили для его визуализации.

    import { useFocusRing } from '@react-aria/focus';
    
    function FocusableButton(props) {
      let { isFocusVisible, focusProps } = useFocusRing();
      return (
        <button {...focusProps} style={{ outline: isFocusVisible ? '2px solid blue' : 'none' }}>
          {props.children}
        </button>
      );
    }
  • useFocus — предоставляет возможность отслеживать события onFocus и onBlur, что полезно для кастомных компонентов без стандартного <button> или <input>.

  • FocusScope — компонент, позволяющий ограничить фокус внутри определённой области (например, модальные окна или выпадающие меню).

    import { FocusScope } from '@react-aria/focus';
    
    <FocusScope contain restoreFocus autoFocus>
      <div>
        <input type="text" placeholder="Введите текст" />
        <button>Закрыть</button>
      </div>
    </FocusScope>

    Параметры:

    • contain — блокирует фокус внутри области.
    • restoreFocus — возвращает фокус на предыдущий элемент после закрытия области.
    • autoFocus — автоматически ставит фокус на первый доступный элемент при монтировании.

Клавиатурная навигация

React Aria стандартизирует взаимодействие с клавиатурой через хуки для списков, вкладок, меню и таблиц:

  • useListBox / useOption — управление фокусом и выбором элементов списка с клавиатуры. Поддерживается навигация стрелками, Home/End и PageUp/PageDown.

    import { useListBox, useOption } from '@react-aria/listbox';
    import { useListState } from '@react-stately/list';
    
    function ListBox({ items }) {
      let state = useListState({ items });
      let ref = React.useRef();
      let { listBoxProps } = useListBox({ autoFocus: true }, state, ref);
    
      return (
        <ul {...listBoxProps} ref={ref}>
          {items.map(item => (
            <Option key={item.key} item={item} state={state} />
          ))}
        </ul>
      );
    }
    
    function Option({ item, state }) {
      let ref = React.useRef();
      let { optionProps, isSelected, isFocused } = useOption({ key: item.key }, state, ref);
      return (
        <li {...optionProps} ref={ref} style={{ background: isFocused ? '#ddd' : 'transparent' }}>
          {item.name}
        </li>
      );
    }
  • useTabList / useTab — управление переключением вкладок с клавиатуры (стрелки влево/вправо, Home/End). Позволяет создавать доступные табы без ручной реализации логики фокуса и активации.

  • useMenu / useMenuItem — для контекстных меню, обеспечивая навигацию через стрелки, Enter для выбора и Escape для закрытия.


Семантические роли и ARIA атрибуты

React Aria автоматически добавляет правильные ARIA-атрибуты для компонентов:

  • role="listbox", role="option" для списков.
  • role="tablist", role="tab" для вкладок.
  • role="menu", role="menuitem" для контекстных меню.

Использование хуков гарантирует, что элементы имеют соответствующие aria-selected, aria-disabled, aria-expanded и другие атрибуты, необходимые для совместимости с экранными читалками и вспомогательными технологиями.


Управление последовательностью фокуса

React Aria позволяет контролировать порядок фокусируемых элементов через FocusScope и хуки useFocus. Для сложных интерфейсов рекомендуется:

  1. Группировать элементы логически — фокус не должен прыгать через несвязанные блоки.
  2. Использовать autoFocus для ключевых элементов — например, первого поля формы или активного пункта меню.
  3. Сохранять состояние фокуса — при закрытии модальных окон или навигации между страницами.

Советы по производительности

  • Не создавайте ненужные вложенные FocusScope, это может усложнять управление фокусом.
  • Используйте useListState или useTabState для управления состоянием элементов отдельно от рендеринга.
  • Минимизируйте количество пересоздаваемых колбэков, чтобы не терять фокус при обновлениях.

Примеры комбинаций

Модальное окно с фокусом и клавиатурной навигацией:

import { FocusScope } from '@react-aria/focus';

function Modal({ isOpen, onClose }) {
  if (!isOpen) return null;
  
  return (
    <FocusScope contain restoreFocus autoFocus>
      <div role="dialog" aria-modal="true">
        <input placeholder="Имя" />
        <button onCl ick={onClose}>Закрыть</button>
      </div>
    </FocusScope>
  );
}

Список с клавиатурной навигацией и выбором элементов:

<ListBox items={[{ key: '1', name: 'Элемент 1' }, { key: '2', name: 'Элемент 2' }]} />

Такой подход обеспечивает корректную работу стрелок, Home/End и поддержки экранных читалок без дополнительного кода.


React Aria формирует основу доступного интерфейса, где фокус, клавиатурная навигация и ARIA-атрибуты работают в унисон, обеспечивая полноценную навигацию по элементам и улучшая пользовательский опыт.