From d04d5c49e33b4874e4ee4157f57f6104f5190256 Mon Sep 17 00:00:00 2001 From: Jack Hsu Date: Fri, 15 Sep 2023 13:09:24 -0400 Subject: [PATCH] feat(nx-dev): improve auto-scrolling so it does not interfere with users reading the content --- nx-dev/feature-ai/src/lib/feed-container.tsx | 38 ++++++++++++-------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/nx-dev/feature-ai/src/lib/feed-container.tsx b/nx-dev/feature-ai/src/lib/feed-container.tsx index d4f9c038d0c8b4..7a08caf931027d 100644 --- a/nx-dev/feature-ai/src/lib/feed-container.tsx +++ b/nx-dev/feature-ai/src/lib/feed-container.tsx @@ -4,7 +4,6 @@ import { type JSX, RefObject, useEffect, - useMemo, useRef, useState, } from 'react'; @@ -28,8 +27,6 @@ export function FeedContainer(): JSX.Element { const [startedReply, setStartedReply] = useState(false); const [isStopped, setStopped] = useState(false); - const feedContainer: RefObject | undefined = useRef(null); - const { messages, setMessages, @@ -57,14 +54,28 @@ export function FeedContainer(): JSX.Element { }, }); - const hasReply = useMemo(() => messages.length > 0, [messages]); - + /* + * Determine whether we should scroll to the bottom of new messages. + * Scroll if: + * 1. New message has come in (length > previous length) + * 2. User is close to the bottom of the messages + * + * Otherwise, user is probably reading messages, so don't scroll. + */ + const scrollableWrapperRef: RefObject | undefined = + useRef(null); + const currentMessagesLength = useRef(0); useEffect(() => { - if (feedContainer.current) { - const elements = - feedContainer.current.getElementsByClassName('feed-item'); - elements[elements.length - 1].scrollIntoView({ behavior: 'smooth' }); + if (!scrollableWrapperRef.current) return; + const el = scrollableWrapperRef.current; + let shouldScroll = false; + if (messages.length > currentMessagesLength.current) { + currentMessagesLength.current = messages.length; + shouldScroll = true; + } else if (el.scrollTop + el.clientHeight + 20 >= el.scrollHeight) { + shouldScroll = true; } + if (shouldScroll) el.scrollTo(0, el.scrollHeight); }, [messages, isLoading]); const handleSubmit = (event: FormEvent) => { @@ -100,6 +111,7 @@ export function FeedContainer(): JSX.Element { <> {/*WRAPPER*/}
{/*MAIN CONTENT*/} -
+
0} showRegenerateCta={isStopped} />