@@ -40,14 +40,18 @@ import { signOut } from "next-auth/react";
4040import { useTheme } from "next-themes" ;
4141import Link from "next/link" ;
4242import posthog from "posthog-js" ;
43- import { ReactNode , useEffect , useMemo , useRef , useState } from "react" ;
43+ import { ReactNode , useEffect , useLayoutEffect , useMemo , useRef , useState } from "react" ;
4444import { KeyboardShortcutHint } from "@/app/components/keyboardShortcutHint" ;
4545import { Tooltip , TooltipContent , TooltipTrigger } from "@/components/ui/tooltip" ;
4646import { Separator } from "@/components/ui/separator" ;
4747import { WhatsNewSidebarButton } from "./whatsNewSidebarButton" ;
4848import { UpgradeButton } from "./upgradeButton" ;
4949import { useIsMobile } from "@/hooks/use-mobile" ;
5050
51+ // Retains the sidebar's scroll position across route-driven remounts of the
52+ // `@sidebar` slot. Module-level so it survives remounts but resets on reload.
53+ let lastScrollTop = 0 ;
54+
5155interface SidebarBaseProps {
5256 session : Session | null ;
5357 collapsible ?: "icon" | "offcanvas" | "none" ;
@@ -61,12 +65,27 @@ export function SidebarBase({ session, collapsible = "icon", headerContent, chil
6165 const contentRef = useRef < HTMLDivElement > ( null ) ;
6266 const isMobile = useIsMobile ( ) ;
6367
68+ // The sidebar lives in the `@sidebar` parallel route slot, whose catch-all
69+ // segment remounts on navigation between chats. Persist the scroll position
70+ // across those remounts so it isn't reset to the top each time.
71+ useLayoutEffect ( ( ) => {
72+ const el = contentRef . current ;
73+ if ( ! el ) {
74+ return ;
75+ }
76+ el . scrollTop = lastScrollTop ;
77+ setIsScrolled ( el . scrollTop > 0 ) ;
78+ } , [ ] ) ;
79+
6480 useEffect ( ( ) => {
6581 const el = contentRef . current ;
6682 if ( ! el ) {
6783 return ;
6884 }
69- const handleScroll = ( ) => setIsScrolled ( el . scrollTop > 0 ) ;
85+ const handleScroll = ( ) => {
86+ lastScrollTop = el . scrollTop ;
87+ setIsScrolled ( el . scrollTop > 0 ) ;
88+ } ;
7089 el . addEventListener ( "scroll" , handleScroll ) ;
7190 return ( ) => el . removeEventListener ( "scroll" , handleScroll ) ;
7291 } , [ ] ) ;
0 commit comments