From 3c2bde91b07894d42826cd924eb5f8015d576147 Mon Sep 17 00:00:00 2001 From: akhisud3195 Date: Fri, 11 Jul 2025 20:34:14 +0530 Subject: [PATCH] Prevent forced auto-scroll in playground chat --- apps/rowboat/app/globals.css | 20 +++++ .../playground/components/chat.tsx | 80 ++++++++++++++----- .../playground/components/messages.tsx | 46 +++++------ 3 files changed, 102 insertions(+), 44 deletions(-) diff --git a/apps/rowboat/app/globals.css b/apps/rowboat/app/globals.css index bb403e79..b475fd21 100644 --- a/apps/rowboat/app/globals.css +++ b/apps/rowboat/app/globals.css @@ -127,3 +127,23 @@ body { background: var(--background); color: var(--foreground); } + +/* Playground chat custom scrollbar: hide track background and border */ +.playground-scrollbar::-webkit-scrollbar { + width: 4px; + background: transparent !important; +} +.playground-scrollbar::-webkit-scrollbar-track { + background: transparent !important; + border: none !important; + box-shadow: none !important; +} +.playground-scrollbar::-webkit-scrollbar-thumb { + background: #9ca3af; + border-radius: 4px; +} + +.playground-scrollbar { + scrollbar-width: thin; + scrollbar-color: #9ca3af transparent; +} diff --git a/apps/rowboat/app/projects/[projectId]/playground/components/chat.tsx b/apps/rowboat/app/projects/[projectId]/playground/components/chat.tsx index b933540c..4102cf68 100644 --- a/apps/rowboat/app/projects/[projectId]/playground/components/chat.tsx +++ b/apps/rowboat/app/projects/[projectId]/playground/components/chat.tsx @@ -12,6 +12,7 @@ import { WithStringId } from "@/app/lib/types/types"; import { ProfileContextBox } from "./profile-context-box"; import { USE_TESTING_FEATURE } from "@/app/lib/feature_flags"; import { BillingUpgradeModal } from "@/components/common/billing-upgrade-modal"; +import { ChevronDownIcon } from "@heroicons/react/24/outline"; export function Chat({ chat, @@ -51,6 +52,32 @@ export function Chat({ const [optimisticMessages, setOptimisticMessages] = useState[]>(chat.messages); const [isLastInteracted, setIsLastInteracted] = useState(false); + // --- Scroll/auto-scroll/unread bubble logic --- + const scrollContainerRef = useRef(null); + const [autoScroll, setAutoScroll] = useState(true); + const [showUnreadBubble, setShowUnreadBubble] = useState(false); + + const handleScroll = useCallback(() => { + const container = scrollContainerRef.current; + if (!container) return; + const { scrollTop, scrollHeight, clientHeight } = container; + const atBottom = scrollHeight - scrollTop - clientHeight < 20; + setAutoScroll(atBottom); + if (atBottom) setShowUnreadBubble(false); + }, []); + + useEffect(() => { + const container = scrollContainerRef.current; + if (!container) return; + if (autoScroll) { + container.scrollTop = container.scrollHeight; + setShowUnreadBubble(false); + } else { + setShowUnreadBubble(true); + } + }, [optimisticMessages, loadingAssistantResponse, autoScroll]); + // --- End scroll/auto-scroll logic --- + const getCopyContent = useCallback(() => { return JSON.stringify({ messages: [{ @@ -255,25 +282,40 @@ export function Chat({ )} -
-
- -
+
+ + {showUnreadBubble && ( + + )}
diff --git a/apps/rowboat/app/projects/[projectId]/playground/components/messages.tsx b/apps/rowboat/app/projects/[projectId]/playground/components/messages.tsx index 37540ae5..f7357b43 100644 --- a/apps/rowboat/app/projects/[projectId]/playground/components/messages.tsx +++ b/apps/rowboat/app/projects/[projectId]/playground/components/messages.tsx @@ -1,6 +1,6 @@ 'use client'; import { Spinner } from "@heroui/react"; -import { useEffect, useMemo, useRef, useState } from "react"; +import { useEffect, useMemo, useRef, useState, useCallback } from "react"; import z from "zod"; import { Workflow } from "@/app/lib/types/workflow_types"; import { WorkflowTool } from "@/app/lib/types/workflow_types"; @@ -360,13 +360,11 @@ export function Messages({ showSystemMessage: boolean; showDebugMessages?: boolean; }) { - const messagesEndRef = useRef(null); - let lastUserMessageTimestamp = 0; - let userMessageSeen = false; - - useEffect(() => { - messagesEndRef.current?.scrollIntoView({ behavior: "smooth" }); - }, [messages, loadingAssistantResponse]); + // Remove scroll/auto-scroll state and logic + // const scrollContainerRef = useRef(null); + // const [autoScroll, setAutoScroll] = useState(true); + // const [showUnreadBubble, setShowUnreadBubble] = useState(false); + // Remove handleScroll and useEffect for scroll const renderMessage = (message: z.infer, index: number) => { if (message.role === 'assistant') { @@ -427,7 +425,7 @@ export function Messages({ if (message.role === 'user') { // TODO: add latency support // lastUserMessageTimestamp = new Date(message.createdAt).getTime(); - userMessageSeen = true; + // userMessageSeen = true; return ; } @@ -452,23 +450,21 @@ export function Messages({ ); } + // Just render the messages, no scroll container or unread bubble return ( -
-
- {messages.map((message, index) => { - const renderedMessage = renderMessage(message, index); - if (renderedMessage) { - return ( -
- {renderedMessage} -
- ); - } - return null; - })} - {loadingAssistantResponse && } -
-
+
+ {messages.map((message, index) => { + const renderedMessage = renderMessage(message, index); + if (renderedMessage) { + return ( +
+ {renderedMessage} +
+ ); + } + return null; + })} + {loadingAssistantResponse && }
); } \ No newline at end of file