refactor: timeline style tweaks

This commit is contained in:
Carlos Valente
2025-07-12 18:55:30 +02:00
committed by Carlos Valente
parent cdd021e76d
commit 0eaec1f88f
12 changed files with 427 additions and 162 deletions
@@ -0,0 +1,77 @@
import { RefObject, useCallback, useEffect } from 'react';
function scrollToComponent<ComponentRef extends HTMLElement, ScrollRef extends HTMLElement>(
componentRef: RefObject<ComponentRef> | null,
scrollRef: RefObject<ScrollRef>,
leftOffset: number,
) {
if (!scrollRef.current) {
return;
}
if (!componentRef?.current) {
// If no target component, scroll to start
scrollRef.current.scrollTo({ left: 0, behavior: 'smooth' });
return;
}
const componentRect = componentRef.current.getBoundingClientRect();
const scrollRect = scrollRef.current.getBoundingClientRect();
const left = componentRect.left - scrollRect.left + scrollRef.current.scrollLeft - leftOffset;
scrollRef.current.scrollTo({ left, behavior: 'smooth' });
}
interface UseHorizontalFollowComponentOptions {
followRef: RefObject<HTMLElement | null>;
scrollRef: RefObject<HTMLElement | null>;
doFollow: boolean;
hasSelectedElement?: boolean;
leftOffset?: number;
setScrollFlag?: (newValue: boolean) => void;
}
/**
* This is a copy of useFollowComponent, but for horizontal scrolling
* Designed with the timeline component in mind
*/
export default function useHorizontalFollowComponent({
followRef,
scrollRef,
doFollow,
hasSelectedElement,
leftOffset = 0,
setScrollFlag,
}: UseHorizontalFollowComponentOptions) {
useEffect(() => {
if (!doFollow || !scrollRef.current) {
return;
}
setScrollFlag?.(true);
// Use requestAnimationFrame to ensure the component is fully loaded
window.requestAnimationFrame(() => {
scrollToComponent(
hasSelectedElement ? (followRef as RefObject<HTMLElement>) : null,
scrollRef as RefObject<HTMLElement>,
leftOffset,
);
setScrollFlag?.(false);
});
}, [followRef, scrollRef, doFollow, hasSelectedElement, leftOffset, setScrollFlag]);
const scrollToRefComponent = useCallback(
(componentRef = followRef, containerRef = scrollRef, offset = leftOffset) => {
if (containerRef.current) {
scrollToComponent(
hasSelectedElement ? (componentRef as RefObject<HTMLElement>) : null,
containerRef as RefObject<HTMLElement>,
offset,
);
}
},
[followRef, scrollRef, hasSelectedElement, leftOffset],
);
return scrollToRefComponent;
}