1- import React , { useEffect , useRef } from "react" ;
1+ import React , { useEffect , useRef , useState } from "react" ;
22import { Button } from "@/components/ui/button" ;
33import { RotateCw } from "lucide-react" ;
44
@@ -13,11 +13,43 @@ function ResultAI({
1313 onCompletion : ( ) => void ;
1414 error : Error | undefined ;
1515} ) {
16- const resultRef = useRef < any > ( null ) ;
16+ const scrollRef = useRef < HTMLElement > ( null ) ;
17+ const [ autoScroll , setAutoScroll ] = useState ( false ) ;
1718
1819 useEffect ( ( ) => {
19- resultRef . current . scrollTop = resultRef . current . scrollHeight ;
20- } , [ completion , isLoading ] ) ;
20+ setAutoScroll ( isLoading ) ;
21+ } , [ isLoading ] ) ;
22+
23+ useEffect ( ( ) => {
24+ if ( ! autoScroll ) {
25+ return ;
26+ }
27+ scrollTo ( ) ;
28+ } ) ;
29+
30+ function scrollTo ( ) {
31+ requestAnimationFrame ( ( ) => {
32+ if (
33+ ! scrollRef . current ||
34+ scrollRef . current . scrollHeight ===
35+ scrollRef . current . clientHeight + scrollRef . current . scrollTop
36+ ) {
37+ return ;
38+ }
39+ scrollRef . current . scrollTo ( 0 , scrollRef . current . scrollHeight ) ;
40+ } ) ;
41+ }
42+
43+ function onScroll ( e : HTMLElement ) {
44+ if ( ! isLoading ) {
45+ return ;
46+ }
47+ const hitBottom = e . scrollTop + e . clientHeight >= e . scrollHeight - 15 ;
48+ if ( hitBottom === autoScroll ) {
49+ return ;
50+ }
51+ setAutoScroll ( hitBottom ) ;
52+ }
2153
2254 return (
2355 < div className = "h-0 w-full flex-1 sm:max-w-md md:max-w-2xl" >
@@ -30,7 +62,8 @@ function ResultAI({
3062 </ div >
3163 ) }
3264 < article
33- ref = { resultRef }
65+ ref = { scrollRef }
66+ onScroll = { ( e ) => onScroll ( e . currentTarget ) }
3467 className = "max-h-full overflow-auto whitespace-break-spaces rounded-md border p-3 shadow dark:border-0 dark:bg-secondary/90 dark:shadow-none sm:p-5"
3568 >
3669 { error ? (
0 commit comments