diff --git a/frontend/app/src/components/v1/nav/side-nav.tsx b/frontend/app/src/components/v1/nav/side-nav.tsx index 36a79c0711..3301c23091 100644 --- a/frontend/app/src/components/v1/nav/side-nav.tsx +++ b/frontend/app/src/components/v1/nav/side-nav.tsx @@ -30,6 +30,7 @@ import React, { useMemo, useRef, useState, + useLayoutEffect, } from 'react'; interface SideNavProps extends React.HTMLAttributes { @@ -67,6 +68,8 @@ export type SideNavSection = { items: SideNavItem[]; }; +const savedScrollTop = { current: 0 }; + export function SideNav({ className, navItems: navSections }: SideNavProps) { const { sidebarOpen, @@ -89,6 +92,7 @@ export function SideNav({ className, navItems: navSections }: SideNavProps) { const didDragRef = useRef(false); const [showResizeToggle, setShowResizeToggle] = useState(false); const sidebarRef = useRef(null); + const scrollRef = useRef(null); const onNavLinkClick = useCallback(() => { if (isWide) { @@ -246,6 +250,12 @@ export function SideNav({ className, navItems: navSections }: SideNavProps) { [tenantId], ); + useLayoutEffect(() => { + if (scrollRef.current) { + scrollRef.current.scrollTop = savedScrollTop.current; + } + }, []); + const toggleCollapsed = useCallback(() => { setStoredCollapsed(!storedCollapsed); setLiveWidth(null); @@ -455,7 +465,11 @@ export function SideNav({ className, navItems: navSections }: SideNavProps) { <> {/* Scrollable navigation area (keep scrollbar flush to sidebar edge) */}
{ + savedScrollTop.current = scrollRef.current?.scrollTop ?? 0; + }} className="min-h-0 flex-1 overflow-auto overscroll-contain touch-pan-y [-webkit-overflow-scrolling:touch] [scrollbar-gutter:stable] scrollbar-thin scrollbar-track-transparent scrollbar-thumb-muted-foreground" >