From 32f9fc953ccf88df07e45328d9b4fa7787327582 Mon Sep 17 00:00:00 2001 From: Bohdan Date: Wed, 3 Jun 2026 14:33:45 +0300 Subject: [PATCH 1/4] fix(scroll): ResizeObserver on body + direct lenis.resize on music data load --- dashboard/app/dashboard/music/music-client.tsx | 7 +++++++ dashboard/components/smooth-scroll.tsx | 11 +++++++++++ 2 files changed, 18 insertions(+) diff --git a/dashboard/app/dashboard/music/music-client.tsx b/dashboard/app/dashboard/music/music-client.tsx index e68422a..71c9301 100644 --- a/dashboard/app/dashboard/music/music-client.tsx +++ b/dashboard/app/dashboard/music/music-client.tsx @@ -3,6 +3,7 @@ import { useEffect, useRef, useState } from "react"; import { animate } from "framer-motion"; import { keepPreviousData, useQuery } from "@tanstack/react-query"; +import { useLenis } from "lenis/react"; import type { MusicStats } from "@/types/music-stats"; import { TopArtistsChart } from "./top-artists-chart"; import { ProductivityChart } from "./productivity-chart"; @@ -52,6 +53,7 @@ function fmtListened(ms: number): string { export function MusicClient() { const [range, setRange] = useState("last_7d"); + const lenis = useLenis(); const { data, isLoading, isError, error } = useQuery({ queryKey: ["music-stats", range], @@ -61,6 +63,11 @@ export function MusicClient() { refetchInterval: 60_000, }); + // Charts render after data arrives — tell Lenis the page grew + useEffect(() => { + if (data) lenis?.resize(); + }, [data, lenis]); + return (
{/* Range picker */} diff --git a/dashboard/components/smooth-scroll.tsx b/dashboard/components/smooth-scroll.tsx index 085edec..180d3b4 100644 --- a/dashboard/components/smooth-scroll.tsx +++ b/dashboard/components/smooth-scroll.tsx @@ -14,10 +14,21 @@ const OPTIONS: LenisOptions = { function LenisResizer() { const lenis = useLenis(); const pathname = usePathname(); + useEffect(() => { lenis?.scrollTo(0, { immediate: true }); lenis?.resize(); }, [lenis, pathname]); + + // Recalculate scroll height when lazy-loaded content (charts, data) changes + // body height. html { height: 100% } is fixed at viewport — observe body instead. + useEffect(() => { + if (!lenis) return; + const ro = new ResizeObserver(() => lenis.resize()); + ro.observe(document.body); + return () => ro.disconnect(); + }, [lenis]); + return null; } From 6e31c582a77aaab14d7a868262e1ee134085fd9a Mon Sep 17 00:00:00 2001 From: Bohdan Date: Wed, 3 Jun 2026 14:37:06 +0300 Subject: [PATCH 2/4] fix(bg): rescale timer positions on viewport resize --- dashboard/components/timer-field.tsx | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/dashboard/components/timer-field.tsx b/dashboard/components/timer-field.tsx index dffefa4..10cf299 100644 --- a/dashboard/components/timer-field.tsx +++ b/dashboard/components/timer-field.tsx @@ -70,8 +70,18 @@ export function TimerField() { const c = canvas; // stable reference for closures function resize() { + const prevW = c.width; + const prevH = c.height; c.width = window.innerWidth; c.height = window.innerHeight; + if (prevW > 0 && prevH > 0) { + const sx = c.width / prevW; + const sy = c.height / prevH; + for (const t of timersRef.current) { + t.x *= sx; + t.y *= sy; + } + } } resize(); window.addEventListener("resize", resize); From 91d35d8d096bee0ad01a75638996da3e9b7f5b59 Mon Sep 17 00:00:00 2001 From: Bohdan Date: Wed, 3 Jun 2026 14:40:29 +0300 Subject: [PATCH 3/4] Revert "fix(bg): rescale timer positions on viewport resize" This reverts commit 6e31c582a77aaab14d7a868262e1ee134085fd9a. --- dashboard/components/timer-field.tsx | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/dashboard/components/timer-field.tsx b/dashboard/components/timer-field.tsx index 10cf299..dffefa4 100644 --- a/dashboard/components/timer-field.tsx +++ b/dashboard/components/timer-field.tsx @@ -70,18 +70,8 @@ export function TimerField() { const c = canvas; // stable reference for closures function resize() { - const prevW = c.width; - const prevH = c.height; c.width = window.innerWidth; c.height = window.innerHeight; - if (prevW > 0 && prevH > 0) { - const sx = c.width / prevW; - const sy = c.height / prevH; - for (const t of timersRef.current) { - t.x *= sx; - t.y *= sy; - } - } } resize(); window.addEventListener("resize", resize); From 61d89a0aa3bba390d054e6365506e90289cc8cf3 Mon Sep 17 00:00:00 2001 From: Bohdan Date: Wed, 3 Jun 2026 14:42:08 +0300 Subject: [PATCH 4/4] fix(bg): reinit timer positions on viewport resize --- dashboard/components/timer-field.tsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/dashboard/components/timer-field.tsx b/dashboard/components/timer-field.tsx index dffefa4..6a9a0d6 100644 --- a/dashboard/components/timer-field.tsx +++ b/dashboard/components/timer-field.tsx @@ -72,6 +72,10 @@ export function TimerField() { function resize() { c.width = window.innerWidth; c.height = window.innerHeight; + for (const t of timersRef.current) { + t.x = Math.random() * c.width; + t.y = Math.random() * c.height; + } } resize(); window.addEventListener("resize", resize);