dnd-kit icon indicating copy to clipboard operation
dnd-kit copied to clipboard

Autoscroll results in offset for dropzones in sticky parents

Open 5ebastianMeier opened this issue 1 year ago • 1 comments

Problem Description

In a case where draggable elements are placed inside a scrollable area, the auto-scroll feature is super helpful as it scrolls when a currently dragged element comes close to the edges.

Normally this works just fine and the options allow pretty fine grained control of the auto-scroll.

However, when there is a dropzone inside that scrollable area that has position: sticky to prevent it from scrolling out of view, the auto-scroll introduces an offset with every scrolling action that is applied by the auto-scroll to the drop-zone rect before the collision detection is performed.

Optically nothing breaks initially, but a drop-zone that has a hover effect will show the hover effect when the offset bounding box is hovered instead of the visible bounding box.

Sidenotes

While trying to work around this issue I noticed that the auto-scroll feature can be turned off globally by options, but can only be turned off locally by nesting another DndContext. Unfortunately this would break the global drag'n'drop support for the application I'm working on.

It might be a nice addition to be able to exempt certain scroll containers without turning it off globally as well (e.g. via attribute or class name).

On the other hand the ability to nest multiple DndContext where children serve as a configuration device and the parent does all the heavy lifting (drag overlay, drop handling, etc.) would be a nice addition as well. But I guess that's a bigger refactoring and beyond the scope of this issue.

Reproduction

I made a small example in this sandbox: https://codesandbox.io/s/dndkit-autoscroll-with-sticky-dropzone-70m37f

Scrolling horizontally via auto-scroll will prevent reaching the sticky drop zone (dashed border shows successful hovering over the drop zone)

https://user-images.githubusercontent.com/16539774/186900278-f2620221-6004-423e-a1f8-565d050ed761.mov

p.s.: I haven't forgotten about this library and my plans with it, but time is a very limited resource for me right now - more contributions to come soon hopefully ;)

5ebastianMeier avatar Aug 26 '22 12:08 5ebastianMeier

After some more investigation I found a temporary solution to this problem.

I noticed that the measurements for droppables were done before and after the drag, but not while dragging.

Using a number as the measuring frequency for droppables instead of 'optimized' forces the measurement even while dragging and corrects any offset formerly applied to the sticky droppables.

This is my workaround:

  const measuring = useMemo(() => {
    return {
      droppable: {
        strategy: MeasuringStrategy.Always,
        frequency: isDragging ? 500 : MeasuringFrequency.Optimized,
      },
    };
  }, [isDragging]);

5ebastianMeier avatar Aug 31 '22 11:08 5ebastianMeier