Навигация с клавиатуры

Клавиатурная навигация — один из ключевых элементов доступности веб-интерфейсов. Пользователи могут взаимодействовать с приложением без использования мыши по разным причинам: применение экранных считывателей, моторные ограничения, работа с альтернативными устройствами ввода, либо предпочтение быстрого управления с клавиатуры.

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

Библиотека aria-query используется для получения достоверных сведений о ролях ARIA, допустимых атрибутах и их семантике. Эти данные применяются в инструментах разработки, системах валидации доступности и в логике компонентов, реализующих корректное поведение клавиатурной навигации.

Назначение библиотеки aria-query

Библиотека предоставляет структурированные данные из спецификаций ARIA:

  • перечень ролей (roles)
  • сопоставление ролей и HTML-элементов (elementRoles)
  • сопоставление элементов и ролей (roleElements)
  • список поддерживаемых ARIA-свойств (ariaProps)
  • определения ролей (roleDefinitions)

Эти структуры позволяют определить:

  • является ли элемент интерактивным
  • какие состояния и свойства допустимы для конкретной роли
  • какие правила клавиатурной навигации должны применяться

В контексте клавиатурной навигации библиотека используется для анализа ролей компонентов и выбора правильной модели поведения.

Установка и подключение

Установка выполняется через менеджер пакетов:

npm install aria-query

Импорт основных структур данных:

import { roles, elementRoles, roleElements, ariaProps } from "aria-query";

Каждая структура представляет собой Map, содержащую данные спецификации.

Роли и модели клавиатурной навигации

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

Примеры:

Роль Тип навигации
button активация по Enter / Space
menu стрелочная навигация
tablist перемещение между вкладками
listbox вертикальная навигация
grid двумерная навигация

aria-query позволяет программно получить информацию о роли и определить соответствующую модель поведения.

Получение роли:

const buttonRole = roles.get("button");

console.log(buttonRole);

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

Проверка интерактивности элемента

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

aria-query позволяет определить, соответствует ли HTML-элемент определённой роли.

Пример проверки:

import { elementRoles } from "aria-query";

function getRolesForElement(tagName) {
  const rolesSet = elementRoles.get({ name: tagName });

  if (!rolesSet) return [];

  return Array.from(rolesSet);
}

console.log(getRolesForElement("button"));

Полученная информация используется для определения необходимости обработки клавиатурных событий.

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

Фокус — центральное понятие клавиатурной навигации. Правильное управление фокусом обеспечивает предсказуемое перемещение пользователя между элементами интерфейса.

Основные правила:

  • интерактивные элементы должны быть доступны через Tab
  • сложные компоненты управляют фокусом внутри себя
  • фокус не должен «теряться» при динамических изменениях DOM

Пример перемещения фокуса:

function moveFocus(elements, currentIndex, direction) {
  const nextIndex = currentIndex + direction;

  if (nextIndex < 0 || nextIndex >= elements.length) {
    return;
  }

  elements[nextIndex].focus();
}

Такая логика часто применяется в компонентах menu, listbox, tablist.

Реализация стрелочной навигации

Многие ARIA-компоненты используют стрелки клавиатуры для перемещения между элементами.

Пример реализации:

function handleArrowNavigation(event, items, currentIndex) {
  switch (event.key) {
    case "ArrowDown":
      moveFocus(items, currentIndex, 1);
      break;

    case "ArrowUp":
      moveFocus(items, currentIndex, -1);
      break;

    case "Home":
      items[0].focus();
      break;

    case "End":
      items[items.length - 1].focus();
      break;
  }
}

Такой механизм соответствует рекомендациям WAI-ARIA Authoring Practices.

Использование aria-query для определения роли компонента

При создании универсальных компонентов часто требуется автоматически определять роль элемента.

Пример:

function getRoleDefinition(roleName) {
  return roles.get(roleName);
}

const menuRole = getRoleDefinition("menu");

console.log(menuRole.props);

Полученные данные позволяют определить допустимые состояния (aria-expanded, aria-selected и др.).

Это особенно полезно при создании систем проектирования интерфейсов.

Навигация внутри составных виджетов

ARIA определяет понятие composite widget — компонент, внутри которого управление фокусом осуществляется стрелками.

Примеры:

  • menu
  • grid
  • tablist
  • listbox

В таких компонентах используется паттерн roving tabindex.

Принцип roving tabindex

В группе элементов только один элемент имеет tabindex="0", остальные tabindex="-1".

Перемещение фокуса сопровождается изменением tabindex.

Пример:

function updateTabIndex(items, activeIndex) {
  items.forEach((item, index) => {
    item.tabIndex = index === activeIndex ? 0 : -1;
  });
}

Это позволяет:

  • входить в компонент через клавишу Tab
  • перемещаться внутри стрелками
  • сохранять логическую структуру фокуса

Проверка допустимых ARIA-свойств

aria-query содержит информацию о допустимых свойствах для каждой роли.

Пример:

import { ariaProps } from "aria-query";

console.log(ariaProps.get("aria-expanded"));

Это позволяет валидировать состояние компонента перед обработкой клавиатурных событий.

Например, элементы с aria-expanded могут реагировать на клавиши:

  • Enter
  • Space
  • ArrowRight
  • ArrowLeft

Навигация в таб-интерфейсах

Роль tablist предполагает особые правила клавиатурной навигации.

Стандартные клавиши:

Клавиша Действие
ArrowRight следующая вкладка
ArrowLeft предыдущая вкладка
Home первая вкладка
End последняя вкладка

Пример обработчика:

function handleTabKey(event, tabs, currentIndex) {
  if (event.key === "ArrowRight") {
    moveFocus(tabs, currentIndex, 1);
  }

  if (event.key === "ArrowLeft") {
    moveFocus(tabs, currentIndex, -1);
  }
}

aria-query помогает определить, что элемент действительно имеет роль tab, и применить соответствующие правила.

Навигация в списках выбора

Компоненты listbox и menu используют вертикальную навигацию.

Основные клавиши:

  • ArrowDown
  • ArrowUp
  • Home
  • End
  • Enter

Пример:

function handleListNavigation(event, items, index) {
  if (event.key === "ArrowDown") {
    moveFocus(items, index, 1);
  }

  if (event.key === "ArrowUp") {
    moveFocus(items, index, -1);
  }
}

aria-query позволяет убедиться, что элементы списка имеют допустимую роль option или menuitem.

Навигация в двумерных структурах

Компоненты grid требуют поддержки перемещения по строкам и колонкам.

Клавиатурные действия:

Клавиша Действие
ArrowRight следующая колонка
ArrowLeft предыдущая колонка
ArrowDown следующая строка
ArrowUp предыдущая строка

Пример:

function moveGridFocus(grid, row, col, direction) {
  const nextRow = row + direction.row;
  const nextCol = col + direction.col;

  const nextCell = grid[nextRow]?.[nextCol];

  if (nextCell) {
    nextCell.focus();
  }
}

aria-query позволяет определить, что элемент имеет роль gridcell.

Использование aria-query в инструментах разработки

Библиотека активно применяется в системах анализа доступности.

Основные задачи:

  • проверка корректности ролей
  • анализ допустимых ARIA-атрибутов
  • обнаружение нарушений навигации

Многие инструменты линтинга используют aria-query как источник официальных данных спецификации.

Пример применения в валидаторе:

function isValidRole(roleName) {
  return roles.has(roleName);
}

Это позволяет автоматически выявлять ошибки доступности на этапе разработки.

Связь клавиатурной навигации и семантики ARIA

Клавиатурное поведение должно соответствовать семантике роли. Несоответствие может привести к проблемам для пользователей вспомогательных технологий.

Типичные ошибки:

  • использование div с ролью button без обработки Enter и Space
  • отсутствие стрелочной навигации в menu
  • неправильный tabindex в tablist

aria-query предоставляет структурированную модель ролей, позволяющую избежать подобных ошибок при реализации компонентов.

Интеграция этой библиотеки в систему компонентов помогает автоматически определять правила клавиатурной навигации и поддерживать соответствие стандартам доступности.