Skip to content

Commit bc6b4c3

Browse files
authored
improve timeline scrolling with dynamic speed (#10677)
1 parent 30d93e1 commit bc6b4c3

File tree

1 file changed

+32
-15
lines changed

1 file changed

+32
-15
lines changed

web/src/hooks/use-draggable-element.ts

Lines changed: 32 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ function useDraggableElement({
4242
}: DraggableElementProps) {
4343
const [clientYPosition, setClientYPosition] = useState<number | null>(null);
4444
const [initialClickAdjustment, setInitialClickAdjustment] = useState(0);
45+
const [scrollEdgeSize, setScrollEdgeSize] = useState<number>();
4546
const [segments, setSegments] = useState<HTMLDivElement[]>([]);
4647
const { alignStartDateToTimeline, getCumulativeScrollTop } = useTimelineUtils(
4748
{
@@ -52,23 +53,24 @@ function useDraggableElement({
5253
);
5354

5455
const draggingAtTopEdge = useMemo(() => {
55-
if (clientYPosition && timelineRef.current) {
56+
if (clientYPosition && timelineRef.current && scrollEdgeSize) {
5657
return (
57-
clientYPosition - timelineRef.current.offsetTop <
58-
timelineRef.current.clientHeight * 0.03 && isDragging
58+
clientYPosition - timelineRef.current.offsetTop < scrollEdgeSize &&
59+
isDragging
5960
);
6061
}
61-
}, [clientYPosition, timelineRef, isDragging]);
62+
}, [clientYPosition, timelineRef, isDragging, scrollEdgeSize]);
6263

6364
const draggingAtBottomEdge = useMemo(() => {
64-
if (clientYPosition && timelineRef.current) {
65+
if (clientYPosition && timelineRef.current && scrollEdgeSize) {
6566
return (
6667
clientYPosition >
67-
(timelineRef.current.clientHeight + timelineRef.current.offsetTop) *
68-
0.97 && isDragging
68+
timelineRef.current.clientHeight +
69+
timelineRef.current.offsetTop -
70+
scrollEdgeSize && isDragging
6971
);
7072
}
71-
}, [clientYPosition, timelineRef, isDragging]);
73+
}, [clientYPosition, timelineRef, isDragging, scrollEdgeSize]);
7274

7375
const getClientYPosition = useCallback(
7476
(e: MouseEvent | TouchEvent) => {
@@ -290,17 +292,26 @@ function useDraggableElement({
290292
}
291293
});
292294

293-
if (draggingAtTopEdge || draggingAtBottomEdge) {
294-
let newPosition = clientYPosition;
295-
295+
if ((draggingAtTopEdge || draggingAtBottomEdge) && scrollEdgeSize) {
296296
if (draggingAtTopEdge) {
297-
newPosition = scrolled - segmentHeight;
298-
timelineRef.current.scrollTop = newPosition;
297+
const intensity = Math.max(
298+
0,
299+
(scrollEdgeSize - (clientYPosition - timelineTopAbsolute)) /
300+
scrollEdgeSize,
301+
);
302+
timelineRef.current.scrollTop -= segmentHeight * intensity;
299303
}
300304

301305
if (draggingAtBottomEdge) {
302-
newPosition = scrolled + segmentHeight;
303-
timelineRef.current.scrollTop = newPosition;
306+
const intensity = Math.max(
307+
0,
308+
(clientYPosition -
309+
timelineTopAbsolute -
310+
(timelineRef.current.getBoundingClientRect().height -
311+
scrollEdgeSize)) /
312+
scrollEdgeSize,
313+
);
314+
timelineRef.current.scrollTop += segmentHeight * intensity;
304315
}
305316
}
306317

@@ -436,6 +447,12 @@ function useDraggableElement({
436447
// eslint-disable-next-line react-hooks/exhaustive-deps
437448
}, [timelineCollapsed]);
438449

450+
useEffect(() => {
451+
if (timelineRef.current) {
452+
setScrollEdgeSize(timelineRef.current.clientHeight * 0.03);
453+
}
454+
}, [timelineRef]);
455+
439456
return { handleMouseDown, handleMouseUp, handleMouseMove };
440457
}
441458

0 commit comments

Comments
 (0)