diff --git a/chat/src/App.tsx b/chat/src/App.tsx index 636cb3fe49..377a6e5225 100644 --- a/chat/src/App.tsx +++ b/chat/src/App.tsx @@ -1,4 +1,4 @@ -import React from "react"; +import React, { useEffect, useRef } from "react"; import { DndProvider, useDrop } from "react-dnd"; import { HTML5Backend } from "react-dnd-html5-backend"; import { @@ -8,9 +8,11 @@ import { UserList, UsersTyping, } from "./features"; -import { ChatProvider, DrawerProvider, useDrawer } from "./hooks"; +import { ChatProvider, DrawerProvider, useChat, useDrawer } from "./hooks"; import "./App.css"; +const SCROLL_CANCEL_THRESHOLD = 200; + export function App() { return ( @@ -28,6 +30,30 @@ function AppInner() { accept: "drawer", }); const { open, config } = useDrawer(); + const contentWrapper = useRef(null); + const initiallyScrolledDown = useRef(false); + const { messages } = useChat(); + + useEffect(() => { + if (messages.length > 0) { + if (initiallyScrolledDown.current) { + /* We only want to scroll back down on a new message + if the user is not scrolled up looking at previous messages. */ + const scrollableDistance = contentWrapper.current.scrollHeight - contentWrapper.current.clientHeight; + const scrolledDistance = contentWrapper.current.scrollTop; + const hasScrolledEnough = scrollableDistance - scrolledDistance >= SCROLL_CANCEL_THRESHOLD; + + if (hasScrolledEnough) { + return; + } + } else { + // Always scroll to the bottom on first load. + initiallyScrolledDown.current = true; + } + + contentWrapper.current.scrollTop = contentWrapper.current.scrollHeight; + } + }, [messages]); return (
@@ -37,14 +63,12 @@ function AppInner() {
-
-
+
{open ? (
{config.content}
) : ( )} -
diff --git a/chat/src/features/chat/ChatMessage.tsx b/chat/src/features/chat/ChatMessage.tsx index ef7623a9d1..5fc949c4e0 100644 --- a/chat/src/features/chat/ChatMessage.tsx +++ b/chat/src/features/chat/ChatMessage.tsx @@ -93,14 +93,9 @@ export function ChatMessage({ export function ChatMessageList() { const { messages } = useChat(); - const messageWrapper = useRef(null); - - useEffect(() => { - messageWrapper.current.scrollTop = messageWrapper.current.scrollHeight; - }, [messages]); return ( -
+
{messages.map((message, index) => (