В React Aria управление состоянием перетаскивания (drag and drop)
реализуется через хук useDrag и связанные с ним утилиты.
Предпросмотр (drag preview) позволяет отображать визуальное
представление элемента, который пользователь перемещает, независимо от
его исходного положения в DOM. Это особенно важно для создания
интерфейсов с высоким уровнем доступности и интерактивности.
Состояние перетаскиваемого элемента Хук
useDrag возвращает объект состояния, содержащий:
isDragging — логическое значение, указывающее, активен
ли процесс перетаскивания.dragProps — свойства, которые нужно привязать к
элементу для корректного инициирования перетаскивания.dragPreviewProps — свойства для компонента, который
будет отображаться как превью.Изоляция превью от DOM-элемента Предпросмотр
обычно создаётся в отдельном контейнере, чтобы его позиция не зависела
от реального элемента в списке. React Aria использует для этого
порталы, позволяя рендерить превью в любом месте
документа, чаще всего в body. Это повышает
производительность и предотвращает нежелательные смещения других
элементов.
Синхронизация позиции превью Позиция превью
рассчитывается на основе текущих координат курсора и размеров исходного
элемента. React Aria предоставляет возможность автоматически отслеживать
смещение (dragOffset) и передавать его в компонент
превью:
import {useDrag} from '@react-aria/dnd';
function DraggableItem({item}) {
let {dragProps, dragPreviewProps, isDragging} = useDrag({id: item.id});
return (
<>
<div {...dragProps}>{item.name}</div>
{isDragging && (
<div {...dragPreviewProps} style={{position: 'fixed', pointerEvents: 'none'}}>
{item.name}
</div>
)}
</>
);
}
В этом примере dragPreviewProps управляет положением
превью, а pointerEvents: 'none' предотвращает перехват
событий мыши.
Для улучшения UX часто требуется стилизованное или анимированное превью. React Aria позволяет:
framer-motion для плавного перемещения превью за
курсором.Пример с кастомным стилем:
<div {...dragPreviewProps} style={{
position: 'fixed',
top: dragOffset.y,
left: dragOffset.x,
transform: 'translate(-50%, -50%)',
background: 'white',
boxShadow: '0 4px 12px rgba(0,0,0,0.15)',
borderRadius: '8px',
padding: '8px',
pointerEvents: 'none'
}}>
{item.name}
</div>
React Aria обеспечивает поддержку ARIA-атрибутов при работе с drag preview:
aria-grabbed указывает, что элемент выбран для
перетаскивания.aria-dropeffect указывает действие при отпускании
(move, copy, link).onDragStart и
onDragEnd.Важно, чтобы визуальное превью не было единственным источником информации о состоянии перетаскивания. Пользователь, использующий клавиатуру или экранный ридер, должен получать текстовые подсказки через ARIA-атрибуты или скрытые элементы.
React Aria поддерживает доступное перетаскивание с клавиатуры. Для этого:
useDrag предоставляет методы
keyboardProps, которые можно присвоить фокусируемым
элементам.Пример интеграции:
let {dragProps, dragPreviewProps, keyboardProps} = useDrag({id: item.id});
<div {...dragProps} {...keyboardProps}>
{item.name}
</div>
{isDragging && <div {...dragPreviewProps}>Перетаскивается: {item.name}</div>}
Для динамических списков, где элементы могут менять размеры или порядок:
useDroppable можно синхронизировать
превью с контейнером, в который элемент будет перемещён, обеспечивая
точное визуальное соответствие.react-virtualized,
react-window) требуют, чтобы превью рендерилось вне зоны
виртуализации, иначе оно может исчезать при прокрутке.pointerEvents: 'none' для превью снижает
количество лишних событий.transform, opacity), чтобы не блокировать
главный поток JavaScript.Предпросмотр при перетаскивании в React Aria — это инструмент, который сочетает визуальное представление, доступность и контроль над состоянием drag-and-drop. Грамотная интеграция превью позволяет создавать интерфейсы с плавной анимацией, поддержкой клавиатуры и экранных читалок, а также обеспечивает высокий уровень UX даже в сложных списках и динамических контейнерах.