From 993137068e376ab3892f2abc5b7ce17fde105522 Mon Sep 17 00:00:00 2001 From: Gregor Lohaus Date: Thu, 18 Jun 2026 02:53:06 +0200 Subject: [PATCH] chat scroll to bottom by default --- src/app/chat/_components/ChatInterface.tsx | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/app/chat/_components/ChatInterface.tsx b/src/app/chat/_components/ChatInterface.tsx index b52fd7f..1d5e92c 100644 --- a/src/app/chat/_components/ChatInterface.tsx +++ b/src/app/chat/_components/ChatInterface.tsx @@ -1,5 +1,5 @@ 'use client' -import { useState, useEffect } from 'react' +import { useState, useEffect, useRef } from 'react' import { useChat } from '@ai-sdk/react' import { DefaultChatTransport, type UIMessage } from 'ai' import { Button } from '~/components/ui/button' @@ -83,14 +83,21 @@ function AuthenticatedChatInterface({ dbMessages, sessionId }: ChatInterfaceProp sendMessage({ text }) } const gsapContext = useGsapContext() + const didInitialScroll = useRef(false) useEffect(() => { - let scroller = gsapContext?.getScroller() - if (scroller instanceof Window) { - return; + const scroller = gsapContext?.getScroller() + if (!scroller || scroller instanceof Window) { + return } - console.log(scroller?.scrollHeight) - scroller?.scrollTo({ behavior: 'smooth', top: scroller.scrollHeight }) - }, [messages]) + // Jump instantly on first open so the chat starts pinned to the bottom; + // animate subsequent updates. Defer a frame so the messages have laid out + // (and any streaming content has grown) before we measure scrollHeight. + const behavior: ScrollBehavior = didInitialScroll.current ? 'smooth' : 'auto' + didInitialScroll.current = true + requestAnimationFrame(() => { + scroller.scrollTo({ behavior, top: scroller.scrollHeight }) + }) + }, [messages, status]) return (
{messages &&