useDraggable
A low-level pointer drag hook. It tracks the drag offset, keeps the pointer captured when it
leaves the element and plays the drag sounds. Window and useSlotDrag build on it.
import { useDraggable } from 'jarvis-react-ui';
const { onPointerDown, dragging } = useDraggable({ onStart, onMove, onEnd, disabled });
Usage
Attach onPointerDown to the drag handle. onMove receives the live offset (dx, dy) from the
drag start; commit the position in onEnd.
import { useState } from 'react';
import type { CSSProperties } from 'react';
import { Panel, useDraggable } from 'jarvis-react-ui';
export default function DragBox() {
const [pos, setPos] = useState({ x: 0, y: 0 });
const [live, setLive] = useState({ dx: 0, dy: 0 });
const { onPointerDown, dragging } = useDraggable({
onMove: (state) => setLive({ dx: state.dx, dy: state.dy }),
onEnd: (state) => {
setPos((p) => ({ x: p.x + state.dx, y: p.y + state.dy }));
setLive({ dx: 0, dy: 0 });
},
});
const offset = {
'--x': `${pos.x + live.dx}px`,
'--y': `${pos.y + live.dy}px`,
} as CSSProperties;
return (
<div className="translate-x-[var(--x)] translate-y-[var(--y)]" style={offset}>
<Panel title={dragging ? 'DRAGGING…' : 'DRAG ME'} className="w-[200px]">
<div
role="presentation"
onPointerDown={onPointerDown}
className="cursor-grab select-none py-4 text-center text-[10px] text-text-secondary active:cursor-grabbing"
>
Grab here · dx {live.dx} · dy {live.dy}
</div>
</Panel>
</div>
);
}
Options
| Option | Type | Description |
|---|---|---|
onStart |
(e: PointerEvent) => void |
Called when the drag begins. |
onMove |
(state: DragState, e: PointerEvent) => void |
Called on every pointer move. |
onEnd |
(state: DragState, e: PointerEvent) => void |
Called on pointer up. |
disabled |
boolean |
Ignores pointer down while true. |
DragState is { dragging, startX, startY, dx, dy }. The hook returns onPointerDown and the
current dragging flag for styling.
Sound
Plays drag_start, loops drag_move while dragging and plays drag_end on release.
Accessibility
Pointer only. Offer a keyboard alternative (e.g. arrow buttons or a slot picker) when dragging is the only way to change a layout.
Related
- useResizable for resize handles.
- useSlotDrag adds snap and swap targets on the slot grid.