From 316c8d85a5ce4457dae26dfc1fb62be67406f018 Mon Sep 17 00:00:00 2001 From: Brendan Kellam <10233483+brendan-kellam@users.noreply.github.com> Date: Thu, 2 Jul 2026 01:49:16 +0000 Subject: [PATCH 1/2] fix(web): maintain sidebar scroll position when navigating between chats Generated with [Linear](https://linear.app/sourcebot/issue/SOU-1483/maintain-sidebar-scroll-position-when-opening-a-e6d7#agent-session-05e85428) Co-authored-by: linear-code[bot] <222613912+linear-code[bot]@users.noreply.github.com> --- .../(app)/@sidebar/components/sidebarBase.tsx | 23 +++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/packages/web/src/app/(app)/@sidebar/components/sidebarBase.tsx b/packages/web/src/app/(app)/@sidebar/components/sidebarBase.tsx index 6083c12e4..6ca76aff4 100644 --- a/packages/web/src/app/(app)/@sidebar/components/sidebarBase.tsx +++ b/packages/web/src/app/(app)/@sidebar/components/sidebarBase.tsx @@ -40,7 +40,7 @@ import { signOut } from "next-auth/react"; import { useTheme } from "next-themes"; import Link from "next/link"; import posthog from "posthog-js"; -import { ReactNode, useEffect, useMemo, useRef, useState } from "react"; +import { ReactNode, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react"; import { KeyboardShortcutHint } from "@/app/components/keyboardShortcutHint"; import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip"; import { Separator } from "@/components/ui/separator"; @@ -48,6 +48,10 @@ import { WhatsNewSidebarButton } from "./whatsNewSidebarButton"; import { UpgradeButton } from "./upgradeButton"; import { useIsMobile } from "@/hooks/use-mobile"; +// Retains the sidebar's scroll position across route-driven remounts of the +// `@sidebar` slot. Module-level so it survives remounts but resets on reload. +let lastScrollTop = 0; + interface SidebarBaseProps { session: Session | null; collapsible?: "icon" | "offcanvas" | "none"; @@ -61,12 +65,27 @@ export function SidebarBase({ session, collapsible = "icon", headerContent, chil const contentRef = useRef(null); const isMobile = useIsMobile(); + // The sidebar lives in the `@sidebar` parallel route slot, whose catch-all + // segment remounts on navigation between chats. Persist the scroll position + // across those remounts so it isn't reset to the top each time. + useLayoutEffect(() => { + const el = contentRef.current; + if (!el) { + return; + } + el.scrollTop = lastScrollTop; + setIsScrolled(el.scrollTop > 0); + }, []); + useEffect(() => { const el = contentRef.current; if (!el) { return; } - const handleScroll = () => setIsScrolled(el.scrollTop > 0); + const handleScroll = () => { + lastScrollTop = el.scrollTop; + setIsScrolled(el.scrollTop > 0); + }; el.addEventListener("scroll", handleScroll); return () => el.removeEventListener("scroll", handleScroll); }, []); From cc29ef0e0ce93b95c2ca08c1588d11776c304b1f Mon Sep 17 00:00:00 2001 From: Brendan Kellam <10233483+brendan-kellam@users.noreply.github.com> Date: Thu, 2 Jul 2026 01:49:37 +0000 Subject: [PATCH 2/2] docs: add changelog entry for #1411 Co-authored-by: linear-code[bot] <222613912+linear-code[bot]@users.noreply.github.com> --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7b89a5c92..54a3135b8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Passed Zoekt index parameters via argv to preserve revision names with punctuation. [#1376](https://github.com/sourcebot-dev/sourcebot/pull/1376) - [EE] Validated OAuth bearer token scopes before allowing access to the Sourcebot MCP resource server. [#1396](https://github.com/sourcebot-dev/sourcebot/pull/1396) - Added HTTP security headers to all web app responses. [#1407](https://github.com/sourcebot-dev/sourcebot/pull/1407) +- Maintained the sidebar scroll position when navigating between chats instead of resetting to the top. [#1411](https://github.com/sourcebot-dev/sourcebot/pull/1411) ## [5.0.4] - 2026-06-18