I'm been working on porting a sortable list from @dnd-kit/core to @dnd-kit/react.
Once thing I've noticed is that if you have a DragDropProvider inside a scrollable container element, if you hit Enter to keyboard-drag an item, then hold down the Up or Down arrow key, you can drag the item entirely outside of the container element, presumably because the auto-scroller doesn't respond fast enough to keep up with the arrow key events.
I've made a temporary workaround to throttle arrow key events to no more than one per 100ms, which seems to stop the issue from happening:
// During keyboard "dragging", disallow repeated keydown events more frequent than 100ms
// dnd-kit 0.5 has a bug where holding down an arrow key can "drag" an element out of its container.
const timeStampRef = useRef<number>(0);
useEventListener(
document,
"keydown",
(event: Event) => {
const e = event as KeyboardEvent;
if (dragMethod === DragMethod.KEYBOARD && e.key.startsWith("Arrow")) {
// tried 50ms, was too fast
if (e.timeStamp - timeStampRef.current < 100) {
e.stopImmediatePropagation(); // stopPropagtion() isn't enough; dnd-kit also listens on *document*
} else {
timeStampRef.current = e.timeStamp;
}
}
},
true,
);
// Don't apply throttling when user is tapping the key (just when they hold it down)
useEventListener(document, "keyup", () => {
timeStampRef.current = 0;
});
(useEventListener() is just a hook that calls addEventListener() on and removeEventListener() on cleanup. dragMethod comes from a custom monitor that you see the code for in #2118.)
I'm been working on porting a sortable list from
@dnd-kit/coreto@dnd-kit/react.Once thing I've noticed is that if you have a DragDropProvider inside a scrollable container element, if you hit Enter to keyboard-drag an item, then hold down the Up or Down arrow key, you can drag the item entirely outside of the container element, presumably because the auto-scroller doesn't respond fast enough to keep up with the arrow key events.
I've made a temporary workaround to throttle arrow key events to no more than one per 100ms, which seems to stop the issue from happening:
(
useEventListener()is just a hook that callsaddEventListener()on andremoveEventListener()on cleanup.dragMethodcomes from a custom monitor that you see the code for in #2118.)