From 137ab4c2ba1a833f6611b4cda20d913a5678388b Mon Sep 17 00:00:00 2001 From: Usman Baig Date: Wed, 18 Mar 2026 18:39:17 +0100 Subject: [PATCH] fix: eliminate sidebar flash on page load for good The sidebar is now invisible (opacity-0) on the initial render. In a single useEffect: read collapsed state from localStorage, then requestAnimationFrame to reveal (opacity-1). React batches the state update with the reveal, so the sidebar appears at its correct width with correct label visibility in one frame. No intermediate states, no hydration mismatch, no transitions on load. --- components/dashboard/Sidebar.tsx | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/components/dashboard/Sidebar.tsx b/components/dashboard/Sidebar.tsx index 4d7fcf2..948ef0d 100644 --- a/components/dashboard/Sidebar.tsx +++ b/components/dashboard/Sidebar.tsx @@ -240,12 +240,15 @@ export default function Sidebar({ const [sites, setSites] = useState([]) const [pendingHref, setPendingHref] = useState(null) const wasCollapsedRef = useRef(false) - const [collapsed, setCollapsed] = useState(true) // Always start collapsed — no hydration mismatch + const [ready, setReady] = useState(false) + const [collapsed, setCollapsed] = useState(true) - // Read saved state after mount — expands smoothly if user had it open + // Read saved state and reveal sidebar in one frame — no flash useEffect(() => { const saved = localStorage.getItem(SIDEBAR_KEY) if (saved === 'false') setCollapsed(false) + // Reveal after state is set — React batches these, so sidebar appears at correct width + requestAnimationFrame(() => setReady(true)) }, []) useEffect(() => { listSites().then(setSites).catch(() => {}) }, []) @@ -339,8 +342,8 @@ export default function Sidebar({ <> {/* Desktop — width transitions, internal layout never changes */}