Расширение существующих определений

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


Структура базовых определений

В aria-query все определения хранятся в виде immutable maps, что обеспечивает их неизменяемость и предсказуемость поведения. Основные объекты:

  • Roles — коллекция ARIA-ролей с их разрешёнными дочерними ролями и атрибутами.
  • Elements — сопоставление HTML-тегов с поддерживаемыми ARIA-ролями.
  • Properties — ARIA-свойства и состояния с их типами и допустимыми значениями.

Каждая роль содержит следующую информацию:

{
  name: 'button',
  baseConcepts: [{ name: 'button', attributes: [] }],
  requiredProps: [],
  props: new Map([['aria-pressed', 'tristate']]),
  superClass: ['widget', 'command'],
}
  • baseConcepts — базовые элементы HTML, на которых эта роль по умолчанию разрешена.
  • requiredProps — обязательные ARIA-свойства для корректного использования роли.
  • props — все свойства и состояния, применимые к роли.
  • superClass — иерархия наследования ролей для логической группировки.

Методы расширения ролей

Для расширения ролей используется функция mergeRoles. Она позволяет добавлять новые свойства, изменять базовые элементы и добавлять новые роли-потомки.

Пример расширения роли button:

import { roles, mergeRoles } from 'aria-query';
import { Map } from 'immutable';

// Создание кастомного свойства
const customProps = new Map([
  ['data-custom', 'boolean']
]);

// Объединение существующей роли с новыми свойствами
const extendedRoles = mergeRoles(
  roles,
  new Map([
    ['button', {
      props: customProps,
      baseConcepts: [{ name: 'button', attributes: [{ name: 'data-role', value: 'custom' }] }]
    }]
  ])
);

Результат — роль button теперь поддерживает пользовательское свойство data-custom и новые атрибуты базовой концепции.


Расширение сопоставления HTML-элементов

aria-query позволяет модифицировать elements, чтобы связать HTML-теги с новыми или изменёнными ARIA-ролями:

import { elements, mergeElements } from 'aria-query';
import { Map } from 'immutable';

const extendedElements = mergeElements(
  elements,
  new Map([
    ['div', [{ name: 'button', attributes: [{ name: 'role', value: 'button' }] }]]
  ])
);

Теперь любой <div> с атрибутом role="button" будет корректно распознаваться как кнопка в соответствии с расширенной картой ролей.


Добавление пользовательских ARIA-свойств

Свойства и состояния ARIA можно расширять через mergeProperties:

import { properties, mergeProperties } from 'aria-query';
import { Map } from 'immutable';

const customProperties = new Map([
  ['aria-custom-state', {
    type: 'string',
    values: ['active', 'inactive', 'pending']
  }]
]);

const extendedProperties = mergeProperties(properties, customProperties);

Теперь новая карта свойств поддерживает aria-custom-state с ограниченным набором значений.


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

  • Immutable maps: при расширении рекомендуется работать с копиями объектов, чтобы не нарушить оригинальные определения.
  • Иерархия ролей: при добавлении новых ролей важно указывать superClass, чтобы не нарушить логическую структуру ARIA.
  • Сопоставление с HTML: расширение элементов должно учитывать семантику, чтобы сохранить доступность.
  • Совместимость: новые свойства и роли должны быть проверены на поддерживаемость браузеров и вспомогательных технологий.

Интеграция с инструментами проверки доступности

Расширенные определения можно использовать с библиотеками типа eslint-plugin-jsx-a11y или собственными тестами на доступность. Пример проверки наличия пользовательских свойств в JSX:

import { extendedRoles } from './customAriaQuery';
import { JSXElement } from 'eslint';

function validateAriaProps(node: JSXElement) {
  const role = node.attributes.role;
  if (role && extendedRoles.has(role)) {
    const props = extendedRoles.get(role).props;
    node.attributes.forEach(attr => {
      if (!props.has(attr.name)) {
        console.warn(`Свойство ${attr.name} не разрешено для роли ${role}`);
      }
    });
  }
}

Это позволяет поддерживать строгий контроль доступности даже при использовании кастомных ARIA-расширений.


Вывод

Расширение определений в aria-query обеспечивает гибкость при работе с ARIA. С помощью mergeRoles, mergeElements и mergeProperties можно:

  • Добавлять кастомные свойства и состояния.
  • Поддерживать новые HTML-концепции.
  • Сохранять совместимость с существующими проверками доступности.

Тщательная настройка этих объектов повышает семантическую корректность интерфейсов и расширяет возможности автоматизированной валидации.