From 653f617d66aa1e5c741254b4d73ad5ce9fed5553 Mon Sep 17 00:00:00 2001 From: Oliver Bryan <04oliverbryan@gmail.com> Date: Wed, 21 Jan 2026 18:32:51 +0000 Subject: [PATCH] scroll backwards in time --- packages/frontend/src/pages/Timeline.tsx | 26 ++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/packages/frontend/src/pages/Timeline.tsx b/packages/frontend/src/pages/Timeline.tsx index 9091c3a..5a049bd 100644 --- a/packages/frontend/src/pages/Timeline.tsx +++ b/packages/frontend/src/pages/Timeline.tsx @@ -4,7 +4,7 @@ import { type IssueResponse, type SprintRecord, } from "@sprint/shared"; -import { useEffect, useMemo, useState } from "react"; +import { useEffect, useMemo, useRef, useState } from "react"; import { IssueModal } from "@/components/issue-modal"; import { useSelection } from "@/components/selection-provider"; import { SprintForm } from "@/components/sprint-form"; @@ -130,14 +130,17 @@ export default function Timeline() { const timelineRange = useMemo(() => { if (sprints.length === 0) return null; const today = toDate(new Date()); + let earliest = toDate(sprints[0].startDate); let latest = toDate(sprints[0].endDate); for (const sprint of sprints) { + const start = toDate(sprint.startDate); const end = toDate(sprint.endDate); + if (start < earliest) earliest = start; if (end > latest) latest = end; } - const rangeStart = today; + const rangeStart = startOfWeek(earliest < today ? earliest : today); const rangeEnd = endOfWeek(addDays(latest, 28)); const totalDays = Math.round((rangeEnd.getTime() - rangeStart.getTime()) / DAY_MS); @@ -183,10 +186,21 @@ export default function Timeline() { const today = toDate(new Date()); if (today < timelineRange.start || today > timelineRange.end) return null; const dayOffset = (today.getTime() - timelineRange.start.getTime()) / DAY_MS; - const left = dayOffset * (WEEK_COLUMN_WIDTH / 7); - return { left: `${left}px`, label: formatTodayLabel(today) }; + const leftPx = dayOffset * (WEEK_COLUMN_WIDTH / 7); + return { leftPx, label: formatTodayLabel(today) }; }, [timelineRange]); + const scrollRef = useRef(null); + const hasAutoScrolled = useRef(false); + + useEffect(() => { + if (!todayMarker || hasAutoScrolled.current) return; + const container = scrollRef.current; + if (!container) return; + container.scrollLeft = Math.max(0, todayMarker.leftPx); + hasAutoScrolled.current = true; + }, [todayMarker]); + const getSprintBarStyle = (sprint: SprintRecord) => { if (!timelineRange) return null; const start = toDate(sprint.startDate); @@ -229,7 +243,7 @@ export default function Timeline() { {selectedOrganisationId && selectedProjectId && sprints.length > 0 && (
-
+