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

I am not able to scroll to the left of my main container

Open abhayjeetg opened this issue 1 year ago • 4 comments

useAutoScroller's scrollableAncestorRects returns a different length compared with scrollable ancestors, resulting in no scroll, this only occurs when I am scrolling to right and then coming back to the left const index = scrollableAncestors.indexOf(scrollContainer); const scrollContainerRect = scrollableAncestorRects[index];

This is the link : https://github.com/clauderic/dnd-kit/blob/694dcc2f62e5269541fc941fa6c9af46ccd682ad/packages/core/src/hooks/utilities/useAutoScroller.ts#L121C10-L121C10

attached files: MicrosoftTeams-image MicrosoftTeams-image (1)

this is my autoScroll snippet

autoScroll={{
                        canScroll(element) {
                            if (element.id === 'main-container-id') {
                                console.log('element.id', element.id)
                                return true;
                            }
                            console.log('element.id', false)

                            return false;
                        },

                        threshold: {
                            x: 0.2,
                            y: 0.25,
                        },
                        acceleration: 5,
}}

abhayjeetg avatar Dec 01 '23 09:12 abhayjeetg

Also hit this issue, but it happens in both directions (we're building a kanban style board). I haven't dug into the autoScroll logic deeply, but from what I'm seeing my assumption is autoScroll wasn't built for this purpose and instead more so for Sortable/vertical scrolling - where it works very nicely.

jamesthomsondev avatar Dec 15 '23 04:12 jamesthomsondev

Also hit this issue, but it happens in both directions (we're building a kanban style board). I haven't dug into the autoScroll logic deeply, but from what I'm seeing my assumption is autoScroll wasn't built for this purpose and instead more so for Sortable/vertical scrolling - where it works very nicely.

We are building same kind of thing ( kanban boards ) but when I scroll to right and when I come back to the left then scrolling stops and I am not able to drag item to the first Kanban.

abhayjeetg avatar Dec 15 '23 05:12 abhayjeetg

Yep, that's the same issue I'm experiencing. I'm going to dive into it today and write up a custom handler. It may or may not be helpful for your purpose, but regardless, I'll share it with you once I'm done.

Edit: I think I've determined it's actually a referencing of stale data problem. I've noticed that if I hard refresh the view and try to drag things around it bugs out, but if I do something (e.g. add an item) in a column, it seems to update the data and scrolling works as expected. Currently looking into the measuring config, but the docs are very out of date with the src code so it's a bit hard to decipher.

jamesthomsondev avatar Dec 17 '23 22:12 jamesthomsondev

Alright, so, while I think my comment in the edit above is why the scrolling doesn't work well for us, I couldn't figure out a way to correct it via the options provided for autoScroll. So, I ended up rolling my own.

It's quite specific for our case and only handles horizontal scrolling, but here it is anyway (I've only supplied the pieces that are relevant):

// The number of pixels from the edge of the viewport to start scrolling.
const EDGE_THRESHOLD = 150
// The number of pixels to scroll when the draggable is near the edge of the viewport.
const EDGE_SCROLL_SPEED = 25
const columnsRef = useRef<HTMLDivElement>(null)

<DndContext
      // autoScroll doesn't work with our Kanban style layout
      // so for now, we're disabling it and rolling our own scroll behavior
      autoScroll={false}
      onDragMove={handleDragMove}
    >
      <Columns ref={columnsRef}>
        // ...
      </Columns>
</DndContext>
const handleDragMove = (event: DragMoveEvent): void => {
    const viewport = columnsRef.current

    const {
      active: { rect },
    } = event

    if (viewport && rect.current.translated) {
      const doc = window.document.documentElement
      const draggable = rect.current.translated

      // The viewport doesn't fill the entire document, so we need to account for that.
      const viewportX = doc.offsetWidth - viewport.offsetWidth
      // This is useful to balance out the scroll threshold on both sides of the viewport.
      // Otherwise we're just calculating from the left side of the draggable, which, depending
      // on the width of the draggable, can make it feel like the viewport/scroll behaviour isn't very responsive.
      const draggableCenterPoint = draggable.width / 2
      const draggableX = draggable.left + draggableCenterPoint - viewportX

      // The following will scroll the viewport by EDGE_SCROLL_SPEED when the draggable is
      // within EDGE_THRESHOLD pixels of the edge of the viewport. It will also prevent
      // scrolling when there is no more scrollable area.
      if (draggableX < EDGE_THRESHOLD && viewport.scrollLeft > 0) {
        viewport.scrollBy(-EDGE_SCROLL_SPEED, 0)
      } else if (
        viewport.offsetWidth - draggableX < EDGE_THRESHOLD &&
        viewport.scrollLeft < viewport.scrollWidth - viewport.offsetWidth
      ) {
        viewport.scrollBy(EDGE_SCROLL_SPEED, 0)
      }
    }
  }

jamesthomsondev avatar Dec 18 '23 02:12 jamesthomsondev