Пользовательские компоненты

Современные интерфейсы редко состоят исключительно из стандартных HTML-элементов. В большинстве веб-приложений используются пользовательские компоненты, создаваемые с помощью фреймворков или Web Components API. Такие элементы могут имитировать стандартные элементы управления — кнопки, списки, вкладки, диалоговые окна — но фактически представляют собой комбинацию <div>, <span> и других базовых тегов.

Библиотека Axe-core анализирует доступность DOM-структуры и выявляет нарушения стандартов Web Content Accessibility Guidelines. При работе с пользовательскими компонентами возникают особенности:

  • элементы могут не иметь корректной семантики;
  • интерактивность реализована через JavaScript;
  • структура DOM отличается от стандартных элементов;
  • взаимодействие может не поддерживать клавиатурную навигацию;
  • ARIA-атрибуты могут использоваться некорректно.

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


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

Обычный HTML-элемент уже содержит семантику. Например:

<button>Отправить</button>

Браузер автоматически предоставляет:

  • фокусировку;
  • активацию клавишей Enter или Space;
  • корректную роль для вспомогательных технологий.

Пользовательский компонент может выглядеть так:

<div class="btn">Отправить</div>

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

Axe-core фиксирует подобные проблемы. Например, правило interactive-supports-focus обнаруживает интерактивные элементы без фокуса.

Исправление требует добавления семантики:

<div 
  class="btn"
  role="button"
  tabindex="0"
>
  Отправить
</div>

При анализе страницы Axe-core проверяет:

  • наличие роли;
  • доступность элемента для клавиатуры;
  • корректность ARIA-атрибутов;
  • взаимодействие с фокусом.

Проверка пользовательских компонентов через Axe-core

Axe-core анализирует DOM-структуру страницы и применяет набор правил доступности. Проверка выполняется функцией axe.run().

Пример базового теста:

import axe from "axe-core";

axe.run(document, {}, function (err, results) {
  if (err) throw err;

  console.log(results.violations);
});

В отчёте отображаются:

  • нарушенное правило;
  • уровень серьёзности;
  • описание проблемы;
  • DOM-элементы, вызвавшие нарушение;
  • рекомендации по исправлению.

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


Проверка компонентов внутри Shadow DOM

Многие пользовательские компоненты создаются через Web Components и используют Shadow DOM для изоляции структуры.

Пример компонента:

class CustomButton extends HTMLElement {
  constructor() {
    super();

    const shadow = this.attachShadow({ mode: "open" });

    const button = document.createElement("button");
    button.textContent = "Сохранить";

    shadow.appendChild(button);
  }
}

customElements.define("custom-button", CustomButton);

Структура внутри Shadow DOM не всегда доступна для стандартных инструментов анализа. Axe-core поддерживает обход таких структур при включении соответствующих параметров.

Пример запуска проверки:

axe.run({
  include: [['custom-button']]
});

Axe-core анализирует:

  • содержимое Shadow DOM;
  • роли элементов;
  • доступность фокусировки;
  • наличие текстовых альтернатив.

Настройка правил для пользовательских компонентов

Некоторые компоненты имеют нестандартную реализацию, поэтому может потребоваться настройка правил Axe-core.

Настройка выполняется через конфигурацию:

axe.configure({
  rules: [
    {
      id: "color-contrast",
      enabled: true
    },
    {
      id: "region",
      enabled: false
    }
  ]
});

Настройки позволяют:

  • отключать нерелевантные правила;
  • активировать дополнительные проверки;
  • адаптировать анализ под архитектуру проекта.

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


Проверка ролей ARIA в компонентах

Пользовательские компоненты часто используют WAI-ARIA для передачи семантики.

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

<div role="tablist">
  <button role="tab" aria-selected="true">Описание</button>
  <button role="tab">Отзывы</button>
</div>

Axe-core проверяет:

  • корректность ролей;
  • допустимые ARIA-атрибуты;
  • соответствие роли и поведения элемента;
  • обязательные свойства.

Пример ошибки:

<div role="button"></div>

Если элемент не поддерживает фокус, правило aria-role будет нарушено.


Проверка клавиатурной навигации

Интерактивные пользовательские компоненты должны поддерживать управление клавиатурой.

Распространённые ошибки:

  • отсутствие tabindex;
  • отсутствие реакции на клавиши;
  • неправильный порядок фокуса.

Пример корректной реализации:

element.addEventListener("keydown", (event) => {
  if (event.key === "Enter" || event.key === " ") {
    activateComponent();
  }
});

Axe-core фиксирует проблемы:

  • элементы с обработчиком клика без клавиатурной поддержки;
  • фокусируемые элементы без интерактивности;
  • элементы с неправильными ролями.

Интеграция с компонентными фреймворками

Пользовательские компоненты широко используются во фреймворках:

  • React
  • Vue.js
  • Angular

В таких приложениях интерфейс формируется динамически, поэтому Axe-core запускается:

  • после рендеринга компонента;
  • после обновления состояния;
  • в тестах компонентов.

Пример для React-тестов:

import { render } from "@testing-library/react";
import axe from "axe-core";

test("component accessibility", async () => {
  const { container } = render(<CustomButton />);

  const results = await axe.run(container);

  expect(results.violations.length).toBe(0);
});

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


Создание собственных правил Axe-core

Иногда стандартных правил недостаточно для проверки сложных компонентов. Axe-core позволяет создавать пользовательские правила.

Пример регистрации правила:

axe.registerRule({
  id: "custom-role-check",
  selector: ".interactive",
  any: ["aria-role-valid"]
});

Компонент может быть проверен по специфическим критериям проекта.

Пользовательские правила включают:

  • селектор элементов;
  • функции проверки;
  • описание ошибки;
  • рекомендации.

Это позволяет адаптировать проверку под архитектуру приложения.


Тестирование сложных UI-паттернов

Некоторые компоненты требуют более сложной проверки доступности:

  • модальные окна;
  • аккордеоны;
  • вкладки;
  • меню;
  • выпадающие списки.

Для таких элементов проверяется:

  1. Фокус при открытии
  2. Возврат фокуса после закрытия
  3. ARIA-состояния
  4. Клавиатурная навигация

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

<div role="dialog" aria-modal="true">
  <h2>Настройки</h2>
  <button>Закрыть</button>
</div>

Axe-core анализирует:

  • наличие роли dialog;
  • наличие заголовка;
  • доступность кнопки закрытия;
  • корректное использование aria-modal.

Оптимизация тестирования компонентов

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

Оптимизация достигается через:

  • тестирование отдельных компонентов;
  • проверку только изменённых областей DOM;
  • интеграцию с системой автоматических тестов.

Пример проверки конкретного элемента:

axe.run({
  include: [['#component-root']]
});

Это значительно ускоряет анализ.


Распространённые ошибки при разработке компонентов

Часто встречающиеся проблемы, выявляемые Axe-core:

Отсутствие текстовых альтернатив

<div role="img"></div>

Неправильные ARIA-роли

<div role="button" aria-checked="true"></div>

Недоступные элементы управления

<span oncl ick="submitForm()">Отправить</span>

Отсутствие связей между элементами

<input type="text">

без соответствующего label.

Исправление подобных проблем значительно повышает доступность интерфейса.


Практика использования Axe-core в компонентных библиотеках

Компонентные библиотеки (design systems) особенно выигрывают от автоматизированных проверок доступности.

Типичный процесс:

  1. разработка компонента;
  2. написание unit-теста;
  3. запуск Axe-core;
  4. анализ нарушений;
  5. исправление проблемы.

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

Такой подход снижает количество ошибок доступности на уровне продукта и обеспечивает соответствие требованиям стандартов WCAG.