From 7285668c52ff11272a41764b0489225192c5d4c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hartmut=20N=C3=B6renberg?= Date: Fri, 22 May 2026 08:38:08 +0200 Subject: [PATCH] fix(timeline): use empty-deps useLayoutEffect for mount scroll to today MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The guard-ref approach broke in React Strict Mode (dev): the ref persisted as `true` across the simulated remount, so the second invocation skipped the scroll — leaving scrollLeft=0 (today-90 at the left edge, not today). An empty-deps useLayoutEffect runs twice in Strict Mode but both executions fire against the same initial `toLeft` and produce the correct result. Co-Authored-By: Claude Sonnet 4.6 --- apps/web/src/components/timeline/TimelineView.tsx | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/apps/web/src/components/timeline/TimelineView.tsx b/apps/web/src/components/timeline/TimelineView.tsx index 0937683..ec4cc2d 100644 --- a/apps/web/src/components/timeline/TimelineView.tsx +++ b/apps/web/src/components/timeline/TimelineView.tsx @@ -689,17 +689,15 @@ function TimelineViewContent({ const pendingLeftCompensationPx = useRef(0); // Flag: scroll viewport to today after the next viewStart-driven re-layout. const pendingScrollToTodayRef = useRef(false); - // Guard: only auto-scroll to today once on initial mount. - const scrolledToTodayOnMount = useRef(false); - // Scroll to today on first mount so the viewport opens with today at the left edge. + // Scroll to today on mount so the viewport opens with today at the left edge. + // Empty deps: intentionally runs once (and twice in React Strict Mode dev, both correct). + useLayoutEffect(() => { - if (scrolledToTodayOnMount.current) return; const el = scrollContainerRef.current; if (!el) return; el.scrollLeft = toLeft(today); - scrolledToTodayOnMount.current = true; - }, [toLeft, today]); + }, []); // Apply scroll compensation synchronously after the canvas grows (left-extend or Today button). useLayoutEffect(() => {