Семантика HTML

Radix UI — это библиотека для создания доступных и высококачественных пользовательских интерфейсов на JavaScript и React. Одной из её ключевых особенностей является строгая приверженность семантике HTML. Использование правильных семантических элементов не только улучшает доступность, но и обеспечивает совместимость с браузерами и вспомогательными технологиями, такими как скринридеры.

Использование семантических элементов

Radix UI стремится к тому, чтобы все компоненты строились на базовых HTML-элементах с предопределёнными ролями и атрибутами ARIA. Например:

  • Кнопки (<button>) автоматически получают все необходимые состояния: disabled, aria-pressed, aria-expanded.
  • Модальные окна используют <div role="dialog"> с правильной привязкой к aria-modal и aria-labelledby.
  • Меню и дропдауны строятся на <ul> и <li> с соответствующими ролями menu и menuitem, обеспечивая правильную навигацию с клавиатуры.

Применение семантических элементов снижает необходимость вручную прописывать ARIA-атрибуты, так как библиотека уже внедряет их по умолчанию. Это делает интерфейсы доступными сразу после внедрения компонента.

Роль ARIA и её автоматизация

Radix UI активно использует ARIA (Accessible Rich Internet Applications) для управления интерактивностью компонентов. Каждый компонент Radix имеет чётко определённые ARIA-роли, которые соответствуют его назначению:

  • aria-expanded — указывает раскрыт ли элемент (например, аккордеон или меню).
  • aria-checked — для элементов выбора, таких как чекбоксы или радио-кнопки.
  • aria-selected — для табов и списков с выбором.
  • aria-disabled — отражает состояние недоступности элемента.

Библиотека гарантирует, что эти атрибуты обновляются автоматически при изменении состояния компонента, что исключает ошибки при ручной настройке.

Контролируемые и неконтролируемые компоненты

Radix UI предоставляет возможность создавать контролируемые и неконтролируемые компоненты:

  • Контролируемые — состояние управляется внешним кодом. Например, состояние выбранного таба или открытое модальное окно управляется через пропсы value и onValueChange.
  • Неконтролируемые — компонент управляет состоянием самостоятельно, используя внутренние механизмы. Например, выпадающее меню автоматически открывается и закрывается при клике на триггер.

С точки зрения семантики HTML, оба подхода сохраняют правильные роли и атрибуты ARIA, что позволяет переключаться между управлением состоянием без потери доступности.

Семантика интерактивных компонентов

Табы (Tabs) Radix UI строит табы с использованием <div role="tablist">, <button role="tab"> и <div role="tabpanel">. Ключевые моменты:

  • Каждый <button> синхронизирован с aria-controls, указывающим на соответствующий <tabpanel>.
  • Атрибут aria-selected отражает активный таб.
  • Поддерживается управление с клавиатуры: стрелки, Home/End.

Аккордеон (Accordion) Аккордеон реализуется через <div role="region"> для панели и <button> для заголовка. Автоматически:

  • Поддерживается aria-expanded.
  • Управление фокусом осуществляется с клавиатуры.
  • Семантика позволяет скринридерам корректно объявлять раскрытые и скрытые панели.

Модальные окна (Dialog) Модальные окна используют <div role="dialog"> и оборачиваются aria-modal="true". Особенности:

  • Триггер открывает диалог, а закрытие восстанавливает фокус на исходном элементе.
  • Внутри модального окна фокус ограничен элементами диалога (focus trap).
  • Скринридеры получают правильное название через aria-labelledby и aria-describedby.

Меню (DropdownMenu) Строится на <ul role="menu"> и <li role="menuitem">. Важные аспекты:

  • Поддержка навигации с клавиатуры (стрелки вверх/вниз, Enter/Space для выбора).
  • Автоматическая установка aria-disabled для недоступных пунктов.
  • Согласованная семантика обеспечивает совместимость с assistive technologies.

Кастомизация и сохранение семантики

Radix UI позволяет кастомизировать стили и поведение компонентов, при этом сохраняя семантическую основу:

  • Компоненты поддерживают asChild проп, который позволяет использовать другой HTML-элемент в качестве корневого, но сохраняет все роли и атрибуты ARIA.
  • Возможность передачи className и style не нарушает встроенную семантику.
  • Для нестандартных элементов можно вручную расширять ARIA-атрибуты без потери доступности.

Выгоды семантики в Radix UI

  • Доступность — интерфейсы работают со скринридерами и клавиатурной навигацией.
  • Совместимость с браузерами — стандартные HTML-элементы ведут себя предсказуемо.
  • Простота поддержки — семантика уменьшает вероятность ошибок при изменении состояния компонентов.
  • Интеграция с фреймворками — React-компоненты Radix легко комбинируются с другими библиотеками без нарушения доступности.

Практический пример использования

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

function ModalExample() {
  return (
    <Dialog.Root>
      <Dialog.Trigger>Открыть диалог</Dialog.Trigger>
      <Dialog.Portal>
        <Dialog.Overlay className="overlay" />
        <Dialog.Content className="modal">
          <Dialog.Title>Заголовок диалога</Dialog.Title>
          <Dialog.Description>Описание содержания диалога</Dialog.Description>
          <button onCl ick={() => console.log('Закрытие')}>Закрыть</button>
        </Dialog.Content>
      </Dialog.Portal>
    </Dialog.Root>
  );
}

В этом примере <Dialog.Content> автоматически получает role="dialog" и aria-modal="true", <Dialog.Title> связывается с модальным окном через aria-labelledby. Это гарантирует корректное взаимодействие с вспомогательными технологиями без дополнительных усилий со стороны разработчика.