diff --git a/frontend/src/assets/arrow-down.svg b/frontend/src/assets/arrow-down.svg new file mode 100644 index 00000000..a4781b89 --- /dev/null +++ b/frontend/src/assets/arrow-down.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/frontend/src/conversation/Conversation.tsx b/frontend/src/conversation/Conversation.tsx index 56f87b6d..b110ec19 100644 --- a/frontend/src/conversation/Conversation.tsx +++ b/frontend/src/conversation/Conversation.tsx @@ -1,4 +1,4 @@ -import { Fragment, useEffect, useRef } from 'react'; +import { Fragment, useEffect, useRef, useState } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import Hero from '../Hero'; import { AppDispatch } from '../store'; @@ -14,6 +14,7 @@ import Send from './../assets/send.svg'; import Spinner from './../assets/spinner.svg'; import { FEEDBACK, Query } from './conversationModels'; import { sendFeedback } from './conversationApi'; +import ArrowDown from './../assets/arrow-down.svg'; export default function Conversation() { const queries = useSelector(selectQueries); @@ -22,10 +23,42 @@ export default function Conversation() { const endMessageRef = useRef(null); const inputRef = useRef(null); - useEffect( - () => endMessageRef?.current?.scrollIntoView({ behavior: 'smooth' }), - [queries.length, queries[queries.length - 1]], - ); + const [hasScrolledToLast, setHasScrolledToLast] = useState(true); + + useEffect(() => { + scrollIntoView(); + }, [queries.length, queries[queries.length - 1]]); + + useEffect(() => { + const observerCallback: IntersectionObserverCallback = (entries) => { + entries.forEach((entry) => { + if (entry.isIntersecting) { + setHasScrolledToLast(true); + } else { + setHasScrolledToLast(false); + } + }); + }; + + const observer = new IntersectionObserver(observerCallback, { + root: null, + threshold: [1, 0.8], + }); + if (endMessageRef.current) { + observer.observe(endMessageRef.current); + } + + return () => { + observer.disconnect(); + }; + }, [endMessageRef.current]); + + const scrollIntoView = () => { + endMessageRef?.current?.scrollIntoView({ + behavior: 'smooth', + block: 'start', + }); + }; const handleQuestion = (question: string) => { dispatch(addQuery({ prompt: question })); @@ -79,13 +112,26 @@ export default function Conversation() { return (
+ {queries.length > 0 && !hasScrolledToLast ? ( + + ) : null} + {queries.length > 0 && (
{queries.map((query, index) => { return (