Screen readers поддержка

Библиотека Shopify Draggable предоставляет мощный инструмент для реализации перетаскивания элементов на веб-страницах. Одним из ключевых аспектов доступности является корректная работа с экранными считывателями (screen readers), что позволяет пользователям с ограничениями зрения взаимодействовать с интерфейсом.


Основные принципы доступности при перетаскивании

При работе с перетаскиваемыми элементами важно соблюдать несколько принципов:

  1. Фокус и порядок табуляции Перетаскиваемые элементы должны оставаться доступными через клавиатуру. Это достигается использованием атрибутов tabindex="0" для элементов, которые могут быть перемещены, чтобы экранные считыватели и клавиатурная навигация распознавали их как интерактивные.

  2. ARIA-атрибуты Для передачи информации о состоянии перетаскивания используются ARIA-атрибуты:

    • aria-grabbed="true/false" — указывает, что элемент выбран для перетаскивания.
    • aria-dropeffect="move" — обозначает возможное действие при отпускании элемента.
    • role="list" и role="listitem" — помогают структурировать контейнеры и элементы для правильного чтения списков.
  3. Динамическое уведомление о действиях Экранные считыватели не могут автоматически отслеживать визуальные изменения DOM. Необходимо использовать aria-live или специальные события для информирования о начале и окончании перетаскивания:

    <div id="live-region" aria-live="polite" style="position:absolute; left:-9999px;"></div>

    При начале перетаскивания:

    document.getElementById('live-region').textContent = 'Элемент выбран для перемещения';

    При завершении:

    document.getElementById('live-region').textContent = 'Элемент перемещен на новое место';

Подключение Draggable с учетом доступности

При создании Draggable необходимо явно указывать селекторы, к которым будет применяться функциональность, а также слушать события для обновления состояния ARIA:

import { Draggable } from '@shopify/draggable';

const container = document.querySelector('.draggable-container');

const draggable = new Draggable(container, {
  draggable: '.draggable-item',
  delay: 150,
  mirror: {
    constrainDimensions: true
  }
});

// Обработка событий для экранных считывателей
draggable.on('drag:start', (evt) => {
  evt.source.setAttribute('aria-grabbed', 'true');
  document.getElementById('live-region').textContent = `Элемент ${evt.source.textContent} выбран для перемещения`;
});

draggable.on('drag:stop', (evt) => {
  evt.source.setAttribute('aria-grabbed', 'false');
  document.getElementById('live-region').textContent = `Элемент ${evt.source.textContent} перемещен`;
});

Особенности реализации:

  • drag:start и drag:stop позволяют синхронизировать ARIA-состояния с действиями пользователя.
  • mirror используется для визуальной репрезентации перетаскиваемого объекта, не влияя на сам DOM элемент, что предотвращает неожиданные изменения для screen readers.

Клавиатурная навигация и перетаскивание

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

  1. Навигация по элементам с помощью Tab и стрелок.
  2. Выбор элемента клавишей Enter или Space.
  3. Перемещение с использованием стрелок в выбранном направлении.
  4. Подтверждение позиции и уведомление через aria-live.

Пример обработки клавиатурного перемещения:

container.addEventListener('keydown', (evt) => {
  const active = document.activeElement;
  if (!active.classList.contains('draggable-item')) return;

  switch(evt.key) {
    case 'ArrowUp':
      container.insertBefore(active, active.previousElementSibling);
      break;
    case 'ArrowDown':
      container.insertBefore(active.nextElementSibling, active);
      break;
  }

  document.getElementById('live-region').textContent = `Элемент ${active.textContent} перемещен с клавиатуры`;
});

Рекомендации по тестированию доступности

  • Использовать экранные считыватели, такие как VoiceOver на macOS и iOS, NVDA или JAWS на Windows.
  • Проверять работу ARIA-состояний и динамических уведомлений.
  • Тестировать клавиатурную навигацию, включая Tab, Shift+Tab и стрелки.
  • Убедиться, что зеркальные элементы (mirror) не создают лишних дублей для считывателей.

Практические советы

  • Каждый перетаскиваемый элемент должен иметь уникальный текст или метку для идентификации.
  • Не использовать визуальные изменения как единственное средство информирования; всегда синхронизировать с ARIA.
  • Встроенные события Draggable позволяют централизованно управлять всеми аспектами доступности.
  • Если необходимо сложное перемещение с множественными контейнерами, каждый контейнер должен иметь свои role и aria-dropeffect.

Эффективная интеграция Shopify Draggable с экранными считывателями повышает общую доступность интерфейса, делая динамические элементы доступными для всех пользователей.