From 7a9b155db310c5adbd3f0e1b7d30f211ac840b15 Mon Sep 17 00:00:00 2001 From: Vedant Mahajan Date: Thu, 21 May 2026 21:21:19 +0530 Subject: [PATCH] fix chat scroll and role section (#972) Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com> Co-authored-by: Claude Opus 4.5 --- apps/web/components/chat/index.tsx | 40 ++++++++++++++++++++++++-- apps/web/components/dashboard-view.tsx | 28 ++++++++++++------ 2 files changed, 58 insertions(+), 10 deletions(-) diff --git a/apps/web/components/chat/index.tsx b/apps/web/components/chat/index.tsx index 19103410..98dc46d7 100644 --- a/apps/web/components/chat/index.tsx +++ b/apps/web/components/chat/index.tsx @@ -248,6 +248,11 @@ export function ChatSidebar({ id: string messages: UIMessage[] } | null>(null) + const [loadedThreadScrollTarget, setLoadedThreadScrollTarget] = useState<{ + id: string + messageCount: number + lastMessageId: string | null + } | null>(null) // Adjust chat height based on scroll position (desktop only, grid mode only) useEffect(() => { @@ -298,6 +303,13 @@ export function ChatSidebar({ useEffect(() => { if (pendingThreadLoad && currentChatId === pendingThreadLoad.id) { setMessages(pendingThreadLoad.messages) + setLoadedThreadScrollTarget({ + id: pendingThreadLoad.id, + messageCount: pendingThreadLoad.messages.length, + lastMessageId: + pendingThreadLoad.messages[pendingThreadLoad.messages.length - 1] + ?.id ?? null, + }) setPendingThreadLoad(null) } }, [currentChatId, pendingThreadLoad, setMessages]) @@ -653,15 +665,39 @@ export function ChatSidebar({ } }, [queuedMessage]) - // Scroll to bottom when a new user message is added + // Scroll to bottom when a new user message is added or a thread is loaded useEffect(() => { + const lastMessageId = messages[messages.length - 1]?.id ?? null + const loadedThreadIsRendered = + loadedThreadScrollTarget && + currentChatId === loadedThreadScrollTarget.id && + messages.length === loadedThreadScrollTarget.messageCount && + lastMessageId === loadedThreadScrollTarget.lastMessageId + + if (loadedThreadIsRendered) { + // Trigger the same scroll behavior as the button after loaded messages render. + scrollToBottom() + setTimeout(scrollToBottom, 50) + setTimeout(scrollToBottom, 150) + setTimeout(() => { + scrollToBottom() + setLoadedThreadScrollTarget(null) + }, 300) + return + } const lastMessage = messages[messages.length - 1] if (lastMessage?.role === "user" && messagesContainerRef.current) { scrollToBottom() } else { checkIfScrolledToBottom() } - }, [messages, checkIfScrolledToBottom, scrollToBottom]) + }, [ + currentChatId, + loadedThreadScrollTarget, + messages, + checkIfScrolledToBottom, + scrollToBottom, + ]) useEffect(() => { const isStreaming = status === "streaming" diff --git a/apps/web/components/dashboard-view.tsx b/apps/web/components/dashboard-view.tsx index 38f13ee3..64f601fb 100644 --- a/apps/web/components/dashboard-view.tsx +++ b/apps/web/components/dashboard-view.tsx @@ -268,6 +268,22 @@ const PROFESSION_LABELS: { { value: "medical", label: "Medical" }, ] +function getChangeProfessionPrompt(profession: Profession): string { + const prompts: Record, string> = { + developer: "Not a developer?", + research: "Not a researcher?", + finance: "Not in finance?", + design: "Not a designer?", + legal: "Not in the legal field?", + marketing: "Not in marketing?", + medical: "Not in healthcare?", + } + if (profession === "default") { + return "Not your role?" + } + return prompts[profession] ?? "Not your role?" +} + // Static plugin metadata — shared between PluginPromoCard and RecommendedPluginsCard const PLUGIN_STATIC = [ { @@ -353,7 +369,7 @@ function RecommendedPluginsCard({ return PLUGIN_STATIC.map((p) => ({ ...p, connected: connected[p.id] ?? false, - onClick: onClicks[p.id]!, + onClick: onClicks[p.id] ?? (() => {}), })) }, [hasMcp, connectedProviders, onOpenPlugins, onOpenIntegrations]) @@ -446,11 +462,7 @@ function RecommendedPluginsCard({ onClick={() => setIsEditing(true)} className="text-left px-2 pb-1 text-[10px] text-fg-faint hover:text-fg-muted transition-colors cursor-pointer" > - Not a{" "} - {PROFESSION_LABELS.find( - (p) => p.value === profession, - )?.label.toLowerCase()} - ? Change → + {getChangeProfessionPrompt(profession)} Change role → )} @@ -525,7 +537,7 @@ function PluginPromoCard({ return PLUGIN_STATIC.map((p) => ({ ...p, connected: connected[p.id] ?? false, - onClick: onClicks[p.id]!, + onClick: onClicks[p.id] ?? (() => {}), })).filter((p) => !p.connected) }, [hasMcp, connectedProviders, onOpenPlugins, onOpenIntegrations]) @@ -628,7 +640,7 @@ export function DashboardView({ onOpenSearch, onOpenIntegrations, onOpenPlugins, - onNavigateToMemories, + onNavigateToMemories: _onNavigateToMemories, onNavigateToGraph, onOpenDocument, onHighlightsChat,