Современные веб-приложения активно используют динамическое изменение DOM: элементы создаются программно, интерфейс перестраивается без перезагрузки страницы, компоненты управляются состоянием приложения. В таких условиях обычной HTML-семантики часто недостаточно для корректного взаимодействия со вспомогательными технологиями — экранными дикторами, программами управления голосом и другими инструментами доступности.
Спецификация WAI-ARIA (Web Accessibility Initiative – Accessible Rich Internet Applications) вводит систему ролей, состояний и свойств, которые описывают семантику интерфейса независимо от его визуальной структуры. Однако ручное добавление ARIA-атрибутов в динамических интерфейсах становится трудоёмким и подверженным ошибкам.
Библиотека aria-query решает эту проблему, предоставляя программный доступ к спецификации ARIA. Она содержит структурированные данные о ролях, их допустимых свойствах, поддерживаемых HTML-элементах и связях между ними. Это позволяет автоматически формировать корректную ARIA-разметку и проверять её валидность на этапе разработки.
Внутри библиотеки реализован набор коллекций данных, описывающих спецификацию ARIA:
roleselementRolesroleElementsariadomКаждая коллекция представляет собой структуру Map,
содержащую метаданные о доступности.
Пример импорта:
import { roles, elementRoles, roleElements } from "aria-query";
Эти структуры используются для программного анализа HTML-элементов и генерации корректной ARIA-семантики.
Коллекция roles содержит описание всех ARIA-ролей,
включая:
props)Пример получения информации о роли:
import { roles } from "aria-query";
const buttonRole = roles.get("button");
console.log(buttonRole);
Объект роли содержит подробные метаданные:
{
abstract: false,
accessibleNameRequired: true,
childrenPresentational: true,
props: {
"aria-expanded": null,
"aria-pressed": null
},
superClass: [
["roletype", "widget", "command"]
]
}
abstract Показывает, можно ли использовать роль напрямую в DOM.
props Набор допустимых ARIA-атрибутов.
superClass Иерархия наследования ролей.
Использование этих данных позволяет автоматически добавлять поддерживаемые свойства при генерации компонентов интерфейса.
Не каждый HTML-элемент требует ручного указания роли. Многие элементы уже имеют встроенную семантику.
Коллекция elementRoles описывает соответствие
HTML-элементов и ролей.
Пример:
import { elementRoles } from "aria-query";
for (const [element, roles] of elementRoles) {
console.log(element, roles);
}
Структура записи:
{
name: "button"
}
→ Set { "button" }
Это означает, что элемент <button> уже имеет роль
button.
При создании интерфейса программно можно проверять, требуется ли добавление роли.
Пример функции:
import { elementRoles } from "aria-query";
function getImplicitRoles(tagName) {
for (const [element, roles] of elementRoles) {
if (element.name === tagName) {
return [...roles];
}
}
return [];
}
Использование:
getImplicitRoles("button");
// ["button"]
Если элемент уже имеет встроенную роль, добавление role
в DOM не требуется.
Структура roleElements выполняет обратную задачу —
показывает, какие HTML-элементы поддерживают конкретную роль.
Пример:
import { roleElements } from "aria-query";
const elements = roleElements.get("button");
console.log(elements);
Результат:
Set {
{ name: "button" },
{ name: "input", attributes: [{ name: "type", value: "button" }] }
}
Такая информация полезна при генерации HTML-структуры на основе роли.
function getPreferredElement(role) {
const elements = roleElements.get(role);
if (!elements) return null;
return [...elements][0];
}
Пример использования:
getPreferredElement("checkbox");
Результат:
{ name: "input", attributes: [{ name: "type", value: "checkbox" }] }
Это позволяет автоматически выбирать семантически правильный HTML-элемент.
Коллекция aria содержит список всех ARIA-атрибутов и их
типов.
Импорт:
import { aria } from "aria-query";
Получение данных:
const expanded = aria.get("aria-expanded");
console.log(expanded);
Пример структуры:
{
type: "boolean",
allowUndefined: true
}
Эта информация используется для проверки корректности значений.
Пример генерации:
function applyAriaProps(element, roleName) {
const role = roles.get(roleName);
if (!role) return;
for (const prop in role.props) {
if (!element.hasAttribute(prop)) {
element.setAttribute(prop, "false");
}
}
}
Использование:
applyAriaProps(node, "button");
Функция добавляет поддерживаемые свойства, если они отсутствуют.
Некоторые ARIA-атрибуты разрешены только для определённых ролей.
Библиотека позволяет проверить их допустимость.
Пример:
function isAriaPropAllowed(roleName, propName) {
const role = roles.get(roleName);
if (!role) return false;
return propName in role.props;
}
Использование:
isAriaPropAllowed("button", "aria-expanded");
Результат:
true
Иногда интерфейс генерируется на основе абстрактных компонентов. В этом случае необходимо определить подходящую ARIA-роль.
Использование elementRoles:
function detectRole(element) {
const tagName = element.tagName.toLowerCase();
const roles = getImplicitRoles(tagName);
if (roles.length > 0) {
return roles[0];
}
return "generic";
}
Это позволяет создавать доступную разметку даже при динамическом рендеринге компонентов.
Пример генерации доступного переключателя:
function createSwitch(label) {
const button = document.createElement("button");
button.setAttribute("role", "switch");
button.setAttribute("aria-checked", "false");
button.textContent = label;
button.addEventListener("click", () => {
const checked = button.getAttribute("aria-checked") === "true";
button.setAttribute("aria-checked", !checked);
});
return button;
}
Однако можно использовать aria-query для автоматического
анализа роли.
function generateComponent(roleName) {
const element = getPreferredElement(roleName);
if (!element) return null;
const node = document.createElement(element.name);
if (element.attributes) {
element.attributes.forEach(attr => {
node.setAttribute(attr.name, attr.value);
});
}
node.setAttribute("role", roleName);
applyAriaProps(node, roleName);
return node;
}
Использование:
const checkbox = generateComponent("checkbox");
document.body.appendChild(checkbox);
Библиотека активно применяется в инструментах проверки доступности:
Например, eslint-plugin-jsx-a11y использует
aria-query для определения корректности ARIA-атрибутов в
JSX.
В React-приложениях библиотека может использоваться для генерации семантики компонентов.
Пример:
function withAria(roleName, props = {}) {
const role = roles.get(roleName);
if (!role) return props;
const ariaProps = {};
Object.keys(role.props).forEach(prop => {
ariaProps[prop] = props[prop] ?? null;
});
return {
role: roleName,
...ariaProps,
...props
};
}
Использование:
const buttonProps = withAria("button", {
"aria-pressed": false
});
Одно из ключевых преимуществ aria-query — возможность
автоматизировать правила доступности:
Такая автоматизация особенно важна в больших приложениях, где интерфейс создаётся компонентными системами.
На основе данных aria-query можно формировать схемы
описания доступности компонентов.
Пример структуры:
function createAriaSchema(roleName) {
const role = roles.get(roleName);
if (!role) return null;
return {
role: roleName,
props: Object.keys(role.props),
abstract: role.abstract
};
}
Использование:
createAriaSchema("dialog");
Результат:
{
role: "dialog",
props: ["aria-labelledby", "aria-describedby"],
abstract: false
}
Такие схемы применяются в системах дизайн-компонентов для стандартизации доступности.
При изменении состояния интерфейса ARIA-атрибуты должны обновляться синхронно с DOM.
Использование aria-query позволяет определить, какие
атрибуты связаны с конкретной ролью.
Пример:
function updateAriaState(element, roleName, state) {
const role = roles.get(roleName);
if (!role) return;
Object.entries(state).forEach(([prop, value]) => {
if (prop in role.props) {
element.setAttribute(prop, value);
}
});
}
Пример использования:
updateAriaState(button, "button", {
"aria-pressed": "true"
});
Данные aria-query используются для автоматических тестов
доступности.
Пример проверки:
function validateRole(element) {
const role = element.getAttribute("role");
if (!role) return true;
return roles.has(role);
}
Расширенный вариант может проверять:
Программный подход к генерации ARIA-разметки обеспечивает:
консистентность интерфейса единые правила доступности во всех компонентах
автоматическую проверку спецификации данные библиотеки синхронизированы с ARIA-стандартом
снижение числа ошибок исключается ручное добавление некорректных атрибутов
масштабируемость подходит для крупных интерфейсных систем
Библиотека aria-query превращает спецификацию
доступности из статического документа в программно используемую модель,
позволяя генерировать корректную ARIA-семантику автоматически и
системно.