1- import { useRef , useEffect } from "react" ;
1+ import { useRef , useEffect , UIEvent , useState } from "react" ;
22import { useTranslation } from "react-i18next" ;
33
44import { ChatMessage } from "@/components/ChatMessage" ;
@@ -11,6 +11,8 @@ import type { Chat, IChunkData } from "./types";
1111import { useConnectStore } from "@/stores/connectStore" ;
1212import SessionFile from "./SessionFile" ;
1313import Splash from "./Splash" ;
14+ import { ArrowDown } from "lucide-react" ;
15+ import clsx from "clsx" ;
1416
1517interface ChatContentProps {
1618 activeChat ?: Chat ;
@@ -57,10 +59,11 @@ export const ChatContent = ({
5759 const { t } = useTranslation ( ) ;
5860
5961 const uploadFiles = useChatStore ( ( state ) => state . uploadFiles ) ;
60-
6162 const messagesEndRef = useRef < HTMLDivElement > ( null ) ;
6263
6364 const { scrollToBottom } = useChatScroll ( messagesEndRef ) ;
65+ const scrollRef = useRef < HTMLDivElement > ( null ) ;
66+ const [ isAtBottom , setIsAtBottom ] = useState ( true ) ;
6467
6568 useEffect ( ( ) => {
6669 scrollToBottom ( ) ;
@@ -83,9 +86,22 @@ export const ChatContent = ({
8386
8487 const allMessages = activeChat ?. messages || [ ] ;
8588
89+ const handleScroll = ( event : UIEvent < HTMLDivElement > ) => {
90+ const { scrollHeight, scrollTop, clientHeight } =
91+ event . currentTarget as HTMLDivElement ;
92+
93+ const isAtBottom = scrollHeight - scrollTop - clientHeight < 50 ;
94+
95+ setIsAtBottom ( isAtBottom ) ;
96+ } ;
97+
8698 return (
8799 < div className = "flex-1 overflow-hidden flex flex-col justify-between relative" >
88- < div className = "flex-1 w-full overflow-x-hidden overflow-y-auto border-t border-[rgba(0,0,0,0.1)] dark:border-[rgba(255,255,255,0.15)] custom-scrollbar relative" >
100+ < div
101+ ref = { scrollRef }
102+ className = "flex-1 w-full overflow-x-hidden overflow-y-auto border-t border-[rgba(0,0,0,0.1)] dark:border-[rgba(255,255,255,0.15)] custom-scrollbar relative"
103+ onScroll = { handleScroll }
104+ >
89105 < Greetings />
90106
91107 { activeChat ?. messages ?. map ( ( message , index ) => (
@@ -158,6 +174,23 @@ export const ChatContent = ({
158174 { sessionId && < SessionFile sessionId = { sessionId } /> }
159175
160176 < Splash />
177+
178+ < button
179+ className = { clsx (
180+ "absolute right-4 bottom-4 flex items-center justify-center size-8 border bg-white rounded-full shadow dark:border-[#272828] dark:bg-black dark:shadow-white/15" ,
181+ {
182+ hidden : isAtBottom ,
183+ }
184+ ) }
185+ onClick = { ( ) => {
186+ scrollRef . current ?. scrollTo ( {
187+ top : scrollRef . current ?. scrollHeight ,
188+ behavior : "smooth" ,
189+ } ) ;
190+ } }
191+ >
192+ < ArrowDown className = "size-5" />
193+ </ button >
161194 </ div >
162195 ) ;
163196} ;
0 commit comments