ARIA атрибуты и роли

ARIA (Accessible Rich Internet Applications) — набор атрибутов и ролей, предназначенных для передачи семантики интерфейса вспомогательным технологиям: экранным читалкам, брайлевским дисплеям, голосовому управлению. В Preact, как и в React-подобных библиотеках, ARIA используется напрямую через JSX и тесно связано с виртуальным DOM и механизмом обновления компонентов.

В отличие от стандартных HTML-элементов с уже заданной семантикой, кастомные компоненты и сложные интерактивные элементы (выпадающие списки, вкладки, модальные окна) требуют явного описания поведения и состояния через ARIA.


ARIA-атрибуты в JSX Preact

JSX в Preact поддерживает ARIA-атрибуты без преобразований. Имена атрибутов записываются в kebab-case, как в обычном HTML.

<button aria-pressed={isActive}>
    Фильтр
</button>

Особенности работы:

  • булевы значения передаются как true / false
  • строковые значения — обычные строки
  • Preact не фильтрует ARIA-атрибуты и передаёт их напрямую в DOM
  • динамические изменения состояний автоматически отражаются при перерендере

Роли ARIA и их применение

ARIA-роли (role) описывают назначение элемента, если оно не выражено нативной семантикой HTML.

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

<div role="button" tabIndex={0} aria-pressed={pressed}>
    Переключатель
</div>

Ключевые моменты:

  • роль не добавляет поведение — только семантику
  • при использовании роли интерактивного элемента необходимо вручную реализовывать клавиатурное управление
  • нативные HTML-элементы предпочтительнее, если они подходят по смыслу

Часто используемые ARIA-атрибуты

aria-label и aria-labelledby

Используются для задания текстового описания элемента.

<input aria-label="Поиск" />
<label id="searchLabel">Поиск</label>
<input aria-labelledby="searchLabel" />

Различия:

  • aria-label — прямое текстовое описание
  • aria-labelledby — ссылка на существующий текст в DOM

aria-hidden

Исключает элемент из доступного дерева.

<div aria-hidden={isHidden}>
    Декоративный элемент
</div>

Применение:

  • иконки, дублирующие текст
  • визуальные элементы без смысловой нагрузки
  • временно скрытые части интерфейса

aria-expanded

Описывает состояние раскрытия.

<button aria-expanded={open}>
    Меню
</button>

Часто используется совместно с:

  • aria-controls
  • aria-haspopup

aria-live

Сообщает о динамически обновляемом контенте.

<div aria-live="polite">
    {statusMessage}
</div>

Значения:

  • polite — озвучивание при паузе
  • assertive — немедленное озвучивание

В Preact обновление содержимого автоматически инициирует оповещение вспомогательных технологий.


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

ARIA не управляет фокусом напрямую, но тесно с ним связана. В Preact фокус обычно контролируется через ref.

const inputRef = useRef(null);

useEffect(() => {
    inputRef.current.focus();
}, []);

Комбинация фокуса и ARIA:

  • tabIndex={0} — включение элемента в порядок табуляции
  • tabIndex={-1} — программный фокус без табуляции
  • корректные роли (dialog, menu, listbox) для логичной навигации

Диалоги и модальные окна

Пример модального окна с ARIA:

<div
    role="dialog"
    aria-modal="true"
    aria-labelledby="dialogTitle"
>
    <h2 id="dialogTitle">Настройки</h2>
</div>

Критически важные аспекты:

  • фокус должен перемещаться внутрь диалога
  • элементы вне диалога должны быть недоступны (aria-hidden)
  • при закрытии фокус возвращается в исходную точку

Списки, меню и вкладки

Вкладки

<div role="tablist">
    <button role="tab" aria-selected={active === 0}>
        Профиль
    </button>
    <button role="tab" aria-selected={active === 1}>
        Настройки
    </button>
</div>

Дополнительно используются:

  • aria-controls
  • role="tabpanel"
  • управление клавишами стрелок

Выпадающее меню

<button aria-haspopup="menu" aria-expanded={open}>
    Опции
</button>

<ul role="menu">
    <li role="menuitem">Редактировать</li>
    <li role="menuitem">Удалить</li>
</ul>

Связь ARIA и состояния компонента

В Preact состояние компонента напрямую определяет значения ARIA-атрибутов.

const [checked, setChecked] = useState(false);

<div
    role="checkbox"
    aria-checked={checked}
    onCl ick={() => setChecked(!checked)}
/>

Преимущества:

  • единый источник правды
  • синхронизация UI и доступности
  • отсутствие ручного управления DOM

Ошибки и анти-паттерны

  • дублирование нативной семантики (role="button" на <button>)
  • использование ARIA вместо правильных HTML-элементов
  • отсутствие клавиатурного управления при кастомных ролях
  • применение aria-hidden к интерактивным элементам с фокусом
  • фиктивные aria-label, не отражающие смысл

Проверка доступности в проектах на Preact

Практика включает:

  • автоматические проверки (axe, lighthouse)
  • ручное тестирование клавиатурой
  • проверку экранными читалками
  • аудит семантики компонентов

ARIA в Preact не требует специальных библиотек или обёрток. Корректное использование стандартных атрибутов и ролей в JSX обеспечивает полноценную доступность без усложнения архитектуры приложения.