Клавиатурная навигация

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


Подключение и базовая настройка

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

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

const draggable = new Draggable(document.querySelectorAll('.draggable-list'), {
  draggable: '.draggable-item',
  plugins: [Plugins.KeyboardSensor],
  keyboard: {
    enabled: true
  }
});

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

  • Plugins.KeyboardSensor — плагин, который обрабатывает события клавиатуры и позволяет перемещать элементы.
  • Опция keyboard.enabled активирует отслеживание нажатий клавиш.
  • Для работы навигации элементы должны быть фокусируемыми (tabindex="0"), иначе события клавиатуры не будут применяться.

Управление фокусом

Draggable использует фокус для определения текущего элемента, которым управляет клавиатура. Важно правильно установить атрибут tabindex:

<ul class="draggable-list">
  <li class="draggable-item" tabindex="0">Элемент 1</li>
  <li class="draggable-item" tabindex="0">Элемент 2</li>
  <li class="draggable-item" tabindex="0">Элемент 3</li>
</ul>
  • Элементы с tabindex="0" включаются в естественный порядок табуляции.
  • При активации Draggable фокус автоматически закрепляется на выбранном элементе.
  • Навигация клавишами не работает, если элемент не может принимать фокус.

Поддерживаемые клавиши

Стандартные клавиши, обрабатываемые плагином KeyboardSensor:

Клавиша Действие
ArrowUp Перемещение элемента вверх по списку
ArrowDown Перемещение элемента вниз по списку
Space Захват или отпуск элемента (toggle drag state)
Enter Аналогично Space, подтверждает выбор элемента
Escape Отмена перемещения, возвращает элемент в исходное положение

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


Обработка событий клавиатуры

Draggable генерирует события, которые помогают отслеживать состояние при навигации с клавиатуры:

draggable.on('drag:start', (event) => {
  console.log('Начало перетаскивания:', event.source);
});

draggable.on('drag:stop', (event) => {
  console.log('Окончание перетаскивания:', event.source);
});

draggable.on('drag:move', (event) => {
  console.log('Перемещение элемента:', event.source, 'на индекс', event.newIndex);
});
  • drag:start срабатывает при захвате элемента через клавиатуру или мышь.
  • drag:move отслеживает изменения позиции в реальном времени.
  • drag:stop фиксирует финальное положение элемента после завершения перемещения.

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


Настройка навигации по сетке

Для сеточных интерфейсов с Draggable клавиатурная навигация может быть настроена отдельно по горизонтали и вертикали:

const draggableGrid = new Draggable(document.querySelectorAll('.grid-list'), {
  draggable: '.grid-item',
  plugins: [Plugins.KeyboardSensor],
  keyboard: {
    enabled: true,
    horizontal: true,
    vertical: true
  }
});
  • horizontal: true позволяет перемещать элементы влево и вправо с помощью ArrowLeft и ArrowRight.
  • vertical: true добавляет управление ArrowUp и ArrowDown.
  • Это особенно важно для таблиц или карточных сеток, где перемещение строго по одной оси ограничивает гибкость.

Управление доступностью

Для обеспечения полного соответствия стандартам WCAG необходимо учитывать следующие моменты:

  1. Фокусировка элементов: каждый перетаскиваемый элемент должен быть доступен через клавишу Tab.
  2. Визуальные индикаторы: при захвате элемента желательно менять его стиль (например, рамку или фон) для наглядного отображения состояния.
  3. Обратная связь для скринридеров: события drag:start и drag:stop можно использовать для обновления атрибутов aria-grabbed и aria-dropeffect.

Пример установки атрибутов:

draggable.on('drag:start', (event) => {
  event.source.setAttribute('aria-grabbed', 'true');
});

draggable.on('drag:stop', (event) => {
  event.source.setAttribute('aria-grabbed', 'false');
});

Рекомендации по интеграции

  • Всегда использовать фокусируемые элементы (tabindex="0") для всех draggable-объектов.
  • Поддерживать визуальные индикаторы захвата и перемещения для ясности действия.
  • Применять события Draggable для синхронизации состояния UI и данных.
  • Проверять работу клавиатурной навигации на всех основных браузерах и с экранными читалками.

Продвинутые сценарии

  1. Сортировка с фильтром и пагинацией Клавиатурная навигация сохраняет корректную работу, если элементы перерисовываются через динамический рендеринг. Важно повторно инициализировать Draggable на новых элементах или использовать метод draggable.destroy() перед повторной инициализацией.

  2. Смешанные сенсоры Можно одновременно использовать мышь, сенсорные экраны и клавиатуру, задавая соответствующие плагины в Draggable:

const draggableMixed = new Draggable(document.querySelectorAll('.multi-sensor-list'), {
  draggable: '.item',
  plugins: [Plugins.MouseSensor, Plugins.TouchSensor, Plugins.KeyboardSensor],
  keyboard: { enabled: true }
});
  1. Обработка сложных сеток с ограничениями Для сеток, где элементы могут перемещаться только в пределах определённых колонок или рядов, можно использовать callback mirror:move для динамической корректировки позиции в реальном времени.

Выводы по клавиатурной навигации

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