SortableJS предоставляет мощный инструмент для реализации перетаскивания элементов в списках, а также поддерживает работу с клавиатурой. Клавиатурная навигация особенно важна для обеспечения доступности интерфейса, когда пользователи не могут использовать мышь или сенсорный экран.
Для активации клавиатурной навигации необходимо использовать опцию
forceFallback и подключить модуль
SortableKeyboardPlugin.
import Sortable from 'sortablejs';
import { Keyboard } from '@shopify/draggable'; // при использовании расширений
const list = document.getElementById('sortable-list');
Sortable.create(list, {
animation: 150,
fallbackOnBody: true,
swapThreshold: 0.65,
forceFallback: true,
keyboard: true
});
Опция keyboard: true позволяет управлять элементами
списка с помощью стандартных клавиш: стрелок, Enter и пробела.
Для корректной работы клавиатурной навигации каждый элемент списка
должен быть фокусируемым. Обычно это достигается добавлением атрибута
tabindex="0":
<ul id="sortable-list">
<li tabindex="0">Элемент 1</li>
<li tabindex="0">Элемент 2</li>
<li tabindex="0">Элемент 3</li>
</ul>
При этом важно, чтобы стиль при фокусе был визуально заметен, например:
li:focus {
outline: 2px solid #007BFF;
background-color: #E9F5FF;
}
SortableJS генерирует стандартные события для всех изменений, включая те, которые инициированы клавиатурой:
start – начало перемещения элемента.move – элемент перемещается, можно отменить или
изменить позицию.end – завершение перемещения, включает как фиксацию,
так и отмену.Пример подписки на события:
Sortable.create(list, {
animation: 150,
keyboard: true,
onEnd: function (evt) {
console.log(`Элемент ${evt.item.textContent} перемещен с позиции ${evt.oldIndex} на ${evt.newIndex}`);
}
});
В некоторых случаях требуется изменить стандартное поведение клавиш.
Для этого можно использовать обработчик события keydown на
контейнере списка и самостоятельно вызывать методы SortableJS:
list.addEventListener('keydown', (event) => {
const item = document.activeElement;
const index = Array.from(list.children).indexOf(item);
if (event.key === 'ArrowUp' && index > 0) {
list.insertBefore(item, list.children[index - 1]);
item.focus();
event.preventDefault();
}
if (event.key === 'ArrowDown' && index < list.children.length - 1) {
list.insertBefore(list.children[index + 1], item);
item.focus();
event.preventDefault();
}
});
Такой подход позволяет создавать полностью кастомизированное управление списком с клавиатуры.
Для повышения доступности рекомендуется использовать атрибуты ARIA:
aria-grabbed="true|false" – указывает, захвачен ли
элемент.aria-dropeffect="move" – описывает действие, которое
выполняется при перемещении.Пример:
<li tabindex="0" aria-grabbed="false" aria-dropeffect="move">Элемент 1</li>
Во время перемещения значения атрибутов необходимо обновлять:
list.addEventListener('keydown', (event) => {
const item = document.activeElement;
if (event.key === ' ') {
const grabbed = item.getAttribute('aria-grabbed') === 'true';
item.setAttribute('aria-grabbed', grabbed ? 'false' : 'true');
event.preventDefault();
}
});
focus + aria-grabbed позволяет пользователю
точно понимать текущий статус элемента и избегать ошибок при
перемещении.Клавиатурная навигация в SortableJS позволяет создавать списки с полной функциональностью перетаскивания, совместимые с современными требованиями доступности и удобства взаимодействия.