From bd194c8bd56e74c22dd480bef85c00509e85ba27 Mon Sep 17 00:00:00 2001 From: Philipinho <16838612+Philipinho@users.noreply.github.com> Date: Mon, 25 May 2026 16:27:55 +0100 Subject: [PATCH] fix(bases): widen kanban auto-scroll hitbox and allow cursor overflow --- .../base/hooks/use-kanban-auto-scroll.ts | 36 +++++++++++++++---- 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/apps/client/src/features/base/hooks/use-kanban-auto-scroll.ts b/apps/client/src/features/base/hooks/use-kanban-auto-scroll.ts index 9958a2e0a..004f83f55 100644 --- a/apps/client/src/features/base/hooks/use-kanban-auto-scroll.ts +++ b/apps/client/src/features/base/hooks/use-kanban-auto-scroll.ts @@ -1,17 +1,41 @@ import { useEffect, RefObject } from "react"; +import { combine } from "@atlaskit/pragmatic-drag-and-drop/combine"; import { autoScrollForElements } from "@atlaskit/pragmatic-drag-and-drop-auto-scroll/element"; +import { unsafeOverflowAutoScrollForElements } from "@atlaskit/pragmatic-drag-and-drop-auto-scroll/unsafe-overflow/element"; + +type CanScrollArgs = { + source: { data: Record }; +}; + +// How far past each edge the cursor can roam and still drive scroll. +// 120px gives users a generous "drag past the column" affordance before +// scrolling stops — matches what other kanbans (Linear, Notion) do. +const OVERFLOW_PX = 120; export function useKanbanAutoScroll( ref: RefObject, - canScroll: ({ - source, - }: { - source: { data: Record }; - }) => boolean = () => true, + canScroll: (args: CanScrollArgs) => boolean = () => true, ) { useEffect(() => { const el = ref.current; if (!el) return; - return autoScrollForElements({ element: el, canScroll }); + return combine( + autoScrollForElements({ + element: el, + canScroll, + getConfiguration: () => ({ maxScrollSpeed: "fast" }), + }), + unsafeOverflowAutoScrollForElements({ + element: el, + canScroll, + getConfiguration: () => ({ maxScrollSpeed: "fast" }), + getOverflow: () => ({ + forTopEdge: { top: OVERFLOW_PX }, + forBottomEdge: { bottom: OVERFLOW_PX }, + forLeftEdge: { left: OVERFLOW_PX }, + forRightEdge: { right: OVERFLOW_PX }, + }), + }), + ); }, [ref, canScroll]); }