ARIA-атрибуты в шаблонах

Slim.js — это современная библиотека для создания веб-компонентов с использованием декларативных шаблонов и реактивного обновления DOM. Одним из важных аспектов разработки доступных интерфейсов является корректное использование ARIA-атрибутов. ARIA (Accessible Rich Internet Applications) позволяет сделать динамические веб-компоненты доступными для пользователей с ограниченными возможностями.

В Slim.js ARIA-атрибуты интегрируются прямо в шаблон компонентов, сохраняя реактивность и синтаксическую чистоту кода.


Привязка ARIA-атрибутов в шаблонах

В Slim.js атрибуты добавляются аналогично стандартным HTML-атрибутам. Для динамических значений используется реактивная привязка через ${}.

import { Slim } from 'slim-js';

class AccessibleButton extends Slim {
  constructor() {
    super();
    this.ariaPressed = false;
  }

  toggle() {
    this.ariaPressed = !this.ariaPressed;
  }

  get template() {
    return Slim.html`
      <button
        @click="${this.toggle}"
        aria-pressed="${this.ariaPressed}"
        aria-label="Переключаемая кнопка">
        Нажми меня
      </button>
    `;
  }
}

customElements.define('accessible-button', AccessibleButton);

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

  • aria-pressed динамически обновляется при изменении свойства ariaPressed.
  • Привязка через ${} позволяет полностью использовать реактивную систему Slim.js.
  • Все стандартные ARIA-атрибуты, включая aria-hidden, aria-expanded, aria-labelledby и aria-describedby, работают аналогично.

Работа с условными ARIA-атрибутами

Slim.js поддерживает условное отображение атрибутов. Это удобно для элементов, которые могут менять состояние.

class AccordionItem extends Slim {
  constructor() {
    super();
    this.open = false;
  }

  toggle() {
    this.open = !this.open;
  }

  get template() {
    return Slim.html`
      <div class="accordion-item">
        <button
          @click="${this.toggle}"
          aria-expanded="${this.open}"
          aria-controls="content">
          Заголовок
        </button>
        <div id="content" ?hidden="${!this.open}" aria-hidden="${!this.open}">
          Контент аккордеона
        </div>
      </div>
    `;
  }
}

customElements.define('accordion-item', AccordionItem);

Особенности:

  • Атрибут aria-expanded отражает текущее состояние компонента.
  • Атрибут aria-hidden используется для скрытия контента от вспомогательных технологий.
  • Символ ?hidden позволяет Slim.js управлять атрибутом hidden в зависимости от логики состояния.

Динамическое управление ARIA через свойства

Slim.js позволяет связывать свойства компонента с ARIA-атрибутами без прямой работы с DOM. Любое изменение свойства автоматически обновляет соответствующий атрибут.

class ModalDialog extends Slim {
  constructor() {
    super();
    this.open = false;
  }

  openDialog() {
    this.open = true;
  }

  closeDialog() {
    this.open = false;
  }

  get template() {
    return Slim.html`
      <div
        role="dialog"
        aria-modal="true"
        ?hidden="${!this.open}"
        aria-labelledby="modal-title">
        <h2 id="modal-title">Диалоговое окно</h2>
        <p>Контент модального окна</p>
        <button @click="${this.closeDialog}">Закрыть</button>
      </div>
    `;
  }
}

customElements.define('modal-dialog', ModalDialog);

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

  • Полная реактивность при открытии и закрытии модального окна.
  • Поддержка всех основных ARIA-атрибутов для диалогов (role="dialog", aria-modal, aria-labelledby).
  • Логика управления состоянием компонента и доступностью объединена в одном месте.

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

  1. Всегда задавать role для сложных элементов Компоненты, имитирующие элементы интерфейса (аккордеоны, вкладки, модальные окна), должны иметь корректный ARIA-роль (role="tab", role="dialog", role="menu").

  2. Использовать динамическое обновление атрибутов Атрибуты aria-expanded, aria-pressed, aria-hidden должны отражать текущее состояние компонента, иначе доступность будет нарушена.

  3. Применять уникальные идентификаторы Для aria-labelledby и aria-describedby рекомендуется использовать уникальные id для связывания элементов.

  4. Сохранять реактивность Slim.js Не следует напрямую изменять DOM-атрибуты через setAttribute; предпочтительнее привязка к свойствам и использование ${}.

  5. Тестировать с вспомогательными технологиями Проверка с экранными читалками и инструментами для оценки доступности помогает выявить пропущенные ARIA-атрибуты и некорректное состояние элементов.


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

Slim.js допускает использование любых нестандартных атрибутов, что позволяет расширять доступность кастомных компонентов:

class CustomToggle extends Slim {
  constructor() {
    super();
    this.active = false;
  }

  toggle() {
    this.active = !this.active;
  }

  get template() {
    return Slim.html`
      <div
        role="switch"
        @click="${this.toggle}"
        aria-checked="${this.active}"
        aria-description="Включение или выключение функции">
        ${this.active ? 'Включено' : 'Выключено'}
      </div>
    `;
  }
}

customElements.define('custom-toggle', CustomToggle);
  • role="switch" и aria-checked позволяют эмулировать функциональность переключателя.
  • Дополнительные атрибуты, такие как aria-description, повышают информативность для пользователей вспомогательных технологий.

Поддержка реактивных ARIA в списках и таблицах

Для элементов с динамическим содержимым, таких как списки и таблицы, Slim.js позволяет управлять ARIA-атрибутами на уровне каждого элемента:

class TodoList extends Slim {
  constructor() {
    super();
    this.items = [
      { text: 'Купить продукты', done: false },
      { text: 'Отправить письмо', done: true }
    ];
  }

  toggle(index) {
    this.items[index].done = !this.items[index].done;
    this.update();
  }

  get template() {
    return Slim.html`
      <ul role="list">
        ${this.items.map((item, i) => Slim.html`
          <li role="listitem">
            <input
              type="checkbox"
              @change="${() => this.toggle(i)}"
              aria-checked="${item.done}"
              ?checked="${item.done}">
            ${item.text}
          </li>
        `)}
      </ul>
    `;
  }
}

customElements.define('todo-list', TodoList);
  • Каждому элементу списка назначается role="listitem".
  • Атрибут aria-checked синхронизирован с состоянием чекбокса.
  • Любое изменение состояния автоматически отражается на DOM благодаря реактивной системе Slim.js.

Использование ARIA-атрибутов в Slim.js обеспечивает совместимость с экранными читалками, улучшает доступность динамических компонентов и сохраняет чистоту кода. Правильная привязка свойств к атрибутам позволяет создавать полностью реактивные, доступные интерфейсы без лишней сложности.