Альтернативы для клавиатуры

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

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


Хуки для клавиатурной навигации

  1. useKeyboard Хук useKeyboard предоставляет объект с обработчиками событий клавиатуры, который можно напрямую передать элементу интерфейса. Он позволяет отслеживать нажатия любых клавиш, включая модификаторы (Shift, Alt, Ctrl) и сочетания клавиш.

    Пример использования:

    import {useKeyboard} from '@react-aria/interactions';
    
    function MyComponent() {
      let {keyboardProps} = useKeyboard({
        onKeyDown: (e) => {
          if (e.key === 'Enter') {
            console.log('Enter нажата');
          }
        }
      });
    
      return <div {...keyboardProps}>Нажмите Enter</div>;
    }

    Ключевое преимущество: можно легко интегрировать обработку горячих клавиш, не заботясь о совместимости с различными браузерами и вспомогательными технологиями.

  2. useSelectableCollection Для компонентов списков, таблиц или меню, где требуется навигация стрелками, применяется хук useSelectableCollection. Он управляет фокусом и выбором элементов при нажатии клавиш ArrowUp, ArrowDown, Home, End.

    Пример для списка:

    import {useSelectableCollection} from '@react-aria/selection';
    import {useListState} from '@react-stately/list';
    
    function SelectableList({items}) {
      let state = useListState({items});
      let {collectionProps, selectionManager} = useSelectableCollection({selectionManager: state.selectionManager});
    
      return (
        <ul {...collectionProps}>
          {items.map(item => (
            <li key={item.key}>{item.name}</li>
          ))}
        </ul>
      );
    }

    Здесь React Aria автоматически обрабатывает навигацию стрелками и управление фокусом на элементах коллекции.

  3. useFocusRing и useFocus Для обеспечения визуального индикатора фокуса и поддержки клавиатурной навигации используются хуки useFocusRing и useFocus. Они управляют состоянием фокуса и помогают создать видимую подсветку элемента при навигации с клавиатуры.

    import {useFocusRing} from '@react-aria/focus';
    
    function FocusableButton() {
      let {focusProps, isFocusVisible} = useFocusRing();
    
      return (
        <button {...focusProps} style={{outline: isFocusVisible ? '2px solid blue' : 'none'}}>
          Кнопка
        </button>
      );
    }

    Такой подход гарантирует, что элементы всегда визуально соответствуют клавиатурной навигации, что критично для доступности.


Обработка альтернативных действий

React Aria поддерживает альтернативные способы взаимодействия с элементами, помимо стандартного клика мышью:

  • Enter и Space для активации кнопок и ссылок.
  • Arrow keys для перемещения между элементами коллекций.
  • Escape для закрытия модальных окон или отмены выбора.
  • Tab и Shift+Tab для перехода между интерактивными элементами.

Использование хуков, таких как useButton, автоматически интегрирует эти поведения:

import {useButton} from '@react-aria/button';

function MyButton({onPress}) {
  let {buttonProps} = useButton({onPress});
  return <button {...buttonProps}>Нажми меня</button>;
}

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


Комбинации с состояниями компонентов

В React Aria клавиатурная навигация тесно связана с состояниями компонентов, управляемыми через React Stately. Например, для меню или вкладок состояние фокуса и выбранного элемента синхронизируется с хуками, которые обрабатывают клавиши. Это исключает необходимость вручную реализовывать сложные схемы focus и aria-selected.

import {useTabs} from '@react-aria/tabs';
import {useTabListState} from '@react-stately/tabs';

function TabsExample() {
  let state = useTabListState({
    defaultSelectedKey: 'tab1',
    items: [
      {key: 'tab1', name: 'Вкладка 1'},
      {key: 'tab2', name: 'Вкладка 2'}
    ]
  });

  let {tabListProps} = useTabs({selectedKey: state.selectedKey, onSelectionChange: state.setSelectedKey});

  return (
    <div {...tabListProps}>
      {state.collection.map(tab => (
        <button key={tab.key}>{tab.name}</button>
      ))}
    </div>
  );
}

Здесь клавиши стрелок автоматически переключают фокус между вкладками, а Enter или Space активируют выбранную вкладку, без дополнительной логики.


Практические рекомендации

  • Использовать хуки React Aria вместо ручного добавления onKeyDown к каждому элементу.
  • Сочетать useKeyboard с useFocusRing для визуальной обратной связи.
  • Для коллекций элементов применять useSelectableCollection или useListState для упрощения навигации стрелками.
  • Проверять доступность с помощью клавиатуры и скринридеров на каждом этапе разработки.

Эти подходы позволяют создавать интерфейсы, полностью поддерживающие альтернативные методы ввода, делая их доступными и предсказуемыми для всех пользователей.