Доступность и клавиатурная навигация

Radix UI — это библиотека низкоуровневых компонентов для React, созданная с фокусом на доступность (accessibility, a11y) и полную поддержку клавиатурной навигации. Компоненты Radix UI предоставляют все необходимые ARIA-атрибуты и обработчики событий, что позволяет создавать интерфейсы, соответствующие стандартам WCAG 2.1, без необходимости ручного внедрения всех тонкостей.


Основные принципы доступности в Radix UI

  1. ARIA-атрибуты и роли Все интерактивные компоненты автоматически добавляют корректные ARIA-атрибуты. Например, для диалоговых окон <Dialog> используются role="dialog", aria-modal="true", а для списков <Listbox>role="listbox" и aria-activedescendant для указания текущего выбранного элемента.

  2. Семантические элементы Radix UI стремится к использованию нативных семантических HTML-элементов там, где это возможно (<button>, <input>), что обеспечивает встроенную поддержку клавиатуры и взаимодействия с экранными читалками.

  3. Фокус и управление фокусом Компоненты автоматически управляют фокусом. Например:

    • При открытии <Dialog> фокус перемещается на первый интерактивный элемент.
    • При закрытии фокус возвращается на элемент, вызвавший диалог.
    • <Tabs> управляет фокусом между вкладками через стрелки клавиатуры.

Клавиатурная навигация в компонентах Radix UI

Radix UI реализует унифицированные паттерны клавиатурного управления, соответствующие ожиданиям пользователей с клавиатурой:

  1. Навигация стрелками

    • Горизонтальные вкладки (<Tabs>) поддерживают ArrowLeft и ArrowRight для переключения между вкладками.
    • Вертикальные списки или меню (<Menu>) используют ArrowUp и ArrowDown для перемещения между элементами.
    • Навигация цикличная: достижение конца списка возвращает к первому элементу.
  2. Выбор элементов

    • Клавиша Enter или Space активирует выбранный элемент (<MenuItem>, <ListboxItem>).
    • Модификаторы и комбинации клавиш могут быть настроены через пропсы компонентов.
  3. Закрытие и отмена действий

    • Escape автоматически закрывает модальные окна, контекстные меню и панели.
    • Фокус возвращается на элемент, инициировавший открытие, что предотвращает потерю позиции при навигации.
  4. Фокусные области (Focus Traps)

    • Диалоги и модальные панели используют focus trap, блокируя перемещение фокуса за пределы активного окна до закрытия.
    • Это реализуется через внутренние обработчики focusin и keydown.

Примеры доступного взаимодействия

Пример Tabs с клавиатурной поддержкой:

import * as Tabs from '@radix-ui/react-tabs';

<Tabs.Root defaultValue="tab1">
  <Tabs.List>
    <Tabs.Trigger value="tab1">Первая вкладка</Tabs.Trigger>
    <Tabs.Trigger value="tab2">Вторая вкладка</Tabs.Trigger>
    <Tabs.Trigger value="tab3">Третья вкладка</Tabs.Trigger>
  </Tabs.List>
  <Tabs.Content value="tab1">Контент первой вкладки</Tabs.Content>
  <Tabs.Content value="tab2">Контент второй вкладки</Tabs.Content>
  <Tabs.Content value="tab3">Контент третьей вкладки</Tabs.Content>
</Tabs.Root>
  • Стрелки ArrowLeft/ArrowRight переключают вкладки.
  • Enter или Space активируют текущую вкладку.
  • Все элементы имеют корректные роли tablist, tab и tabpanel.

Пример диалога с focus trap:

import * as Dialog from '@radix-ui/react-dialog';

<Dialog.Root>
  <Dialog.Trigger>Открыть диалог</Dialog.Trigger>
  <Dialog.Overlay />
  <Dialog.Content>
    <Dialog.Title>Заголовок диалога</Dialog.Title>
    <Dialog.Description>Описание диалога</Dialog.Description>
    <button>Действие</button>
    <Dialog.Close>Закрыть</Dialog.Close>
  </Dialog.Content>
</Dialog.Root>
  • При открытии фокус перемещается на первый интерактивный элемент.
  • Escape закрывает диалог.
  • Фокус возвращается на кнопку, вызвавшую диалог.

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

  • Использовать Radix UI «как есть», без вмешательства в управление фокусом, чтобы сохранить встроенную доступность.
  • Не переопределять ARIA-атрибуты вручную, если компонент их уже предоставляет.
  • Для сложных интерфейсов с кастомной логикой можно использовать хуки Radix, например useFocusRing или useId, чтобы сохранить совместимость с a11y.
  • Проверять доступность с помощью screen reader и инструментов вроде Axe или Lighthouse для контроля соответствия стандартам WCAG.

Radix UI сочетает низкоуровневую гибкость с готовыми к использованию паттернами доступности и клавиатурной навигации, что позволяет строить сложные интерфейсы без потери совместимости с assistive technology.