fix: render empty sidebar shell until client is ready

Previous opacity-0 approach still rendered DOM content which could
flash during SSR hydration. Now render an empty div (just border +
background, no content) at collapsed width until useEffect fires.
Then swap in the real aside with content. Zero DOM content = zero
possible flash of text or icons.
This commit is contained in:
Usman Baig
2026-03-18 18:42:36 +01:00
parent 137ab4c2ba
commit a63dfa231e

View File

@@ -340,13 +340,17 @@ export default function Sidebar({
return ( return (
<> <>
{/* Desktop — width transitions, internal layout never changes */} {/* Desktop — empty shell until ready, then real content */}
<aside {!ready ? (
className={`hidden md:flex flex-col shrink-0 border-r border-neutral-200/60 dark:border-neutral-800/60 bg-white/90 dark:bg-neutral-900/90 backdrop-blur-xl overflow-hidden ${ready ? 'opacity-100' : 'opacity-0'}`} <div className="hidden md:block shrink-0 border-r border-neutral-200/60 dark:border-neutral-800/60 bg-white/90 dark:bg-neutral-900/90 backdrop-blur-xl" style={{ width: COLLAPSED }} />
style={{ width: collapsed ? COLLAPSED : EXPANDED, transition: ready ? 'width 200ms cubic-bezier(0.4, 0, 0.2, 1)' : 'none' }} ) : (
> <aside
{sidebarContent(false)} className="hidden md:flex flex-col shrink-0 border-r border-neutral-200/60 dark:border-neutral-800/60 bg-white/90 dark:bg-neutral-900/90 backdrop-blur-xl overflow-hidden"
</aside> style={{ width: collapsed ? COLLAPSED : EXPANDED, transition: 'width 200ms cubic-bezier(0.4, 0, 0.2, 1)' }}
>
{sidebarContent(false)}
</aside>
)}
{/* Mobile overlay */} {/* Mobile overlay */}
{mobileOpen && ( {mobileOpen && (