Fix workspace board shift wheel drag scroll (#2126)

This commit is contained in:
Neil 2026-05-16 16:34:16 -07:00 committed by GitHub
parent 7d38f5e11f
commit 34b7d08ba5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 35 additions and 6 deletions

View File

@ -333,7 +333,7 @@ export default function WorkspaceKanbanDrawer({
left: drawerLeftCss,
top: 36,
height: 'calc(100% - 36px)',
width: `min(calc(100vw - ${drawerLeftCss}), 1320px)`,
width: `min(calc(100vw - ${drawerLeftCss}), 1294px)`,
opacity: workspaceBoardOpacity
} as React.CSSProperties
}

View File

@ -24,6 +24,19 @@ function isEventInsideElement(event: WheelEvent, element: HTMLElement): boolean
)
}
function pointIsInsideElement(
point: { x: number; y: number } | null,
element: HTMLElement
): boolean {
if (!point) {
return false
}
const rect = element.getBoundingClientRect()
return (
point.x >= rect.left && point.x <= rect.right && point.y >= rect.top && point.y <= rect.bottom
)
}
export function useWorkspaceKanbanShiftWheelScroll(
boardRef: React.RefObject<HTMLElement | null>,
scrollerRef: React.RefObject<HTMLElement | null>,
@ -35,13 +48,23 @@ export function useWorkspaceKanbanShiftWheelScroll(
}
let isWorkspaceDragActive = false
let lastDragPoint: { x: number; y: number } | null = null
const stopTrackingDrag = (): void => {
isWorkspaceDragActive = false
lastDragPoint = null
}
const handleDragStart = (event: DragEvent): void => {
isWorkspaceDragActive = event.dataTransfer ? hasWorkspaceDragData(event.dataTransfer) : false
lastDragPoint = isWorkspaceDragActive ? { x: event.clientX, y: event.clientY } : null
}
const handleDragOver = (event: DragEvent): void => {
if (!isWorkspaceDragActive) {
return
}
lastDragPoint = { x: event.clientX, y: event.clientY }
}
const handleWheel = (event: WheelEvent): void => {
@ -52,7 +75,7 @@ export function useWorkspaceKanbanShiftWheelScroll(
!isWorkspaceDragActive ||
!board ||
!scroller ||
!isEventInsideElement(event, board)
(!isEventInsideElement(event, board) && !pointIsInsideElement(lastDragPoint, board))
) {
return
}
@ -62,20 +85,26 @@ export function useWorkspaceKanbanShiftWheelScroll(
return
}
event.preventDefault()
event.stopPropagation()
event.stopImmediatePropagation()
scroller.scrollLeft += delta
}
document.addEventListener('dragstart', handleDragStart)
document.addEventListener('dragstart', handleDragStart, true)
document.addEventListener('dragover', handleDragOver, true)
document.addEventListener('drop', stopTrackingDrag, true)
document.addEventListener('dragend', stopTrackingDrag, true)
window.addEventListener('blur', stopTrackingDrag)
document.addEventListener('wheel', handleWheel, { passive: false })
// Why: Chromium can cancel the native drag if Shift+wheel reaches default
// scrolling first, so intercept before bubble listeners see the event.
document.addEventListener('wheel', handleWheel, { capture: true, passive: false })
return () => {
document.removeEventListener('dragstart', handleDragStart)
document.removeEventListener('dragstart', handleDragStart, true)
document.removeEventListener('dragover', handleDragOver, true)
document.removeEventListener('drop', stopTrackingDrag, true)
document.removeEventListener('dragend', stopTrackingDrag, true)
window.removeEventListener('blur', stopTrackingDrag)
document.removeEventListener('wheel', handleWheel)
document.removeEventListener('wheel', handleWheel, true)
}
}, [boardRef, enabled, scrollerRef])
}