mirror of
https://github.com/eggent-ai/eggent.git
synced 2026-05-13 15:46:00 +00:00
fix(chat): keep composer pinned and improve scroll behavior
This commit is contained in:
@@ -20,13 +20,13 @@ export default async function DashboardPage() {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="[--header-height:calc(--spacing(14))]">
|
||||
<SidebarProvider className="flex flex-col">
|
||||
<div className="[--header-height:calc(--spacing(14))] h-svh overflow-hidden">
|
||||
<SidebarProvider className="flex h-full flex-col">
|
||||
<SiteHeader title="Chat" />
|
||||
<div className="flex flex-1">
|
||||
<div className="flex min-h-0 flex-1">
|
||||
<AppSidebar />
|
||||
<SidebarInset>
|
||||
<div className="flex flex-1 flex-col h-[calc(100svh-var(--header-height))]">
|
||||
<SidebarInset className="min-h-0">
|
||||
<div className="flex min-h-0 flex-1 flex-col">
|
||||
<ChatPanel />
|
||||
</div>
|
||||
</SidebarInset>
|
||||
|
||||
@@ -180,9 +180,19 @@ export function ChatInput({
|
||||
[chatId]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (input.length > 0) return;
|
||||
|
||||
const textarea = textareaRef.current;
|
||||
if (!textarea) return;
|
||||
|
||||
// Reset textarea height back to a single-row composer after submit/clear.
|
||||
textarea.style.height = "auto";
|
||||
}, [input]);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`border-t bg-background p-4 transition-colors ${isDragging ? "bg-primary/5 border-primary" : ""}`}
|
||||
className={`sticky bottom-0 z-20 shrink-0 border-t bg-background/95 p-4 backdrop-blur supports-[backdrop-filter]:bg-background/80 transition-colors ${isDragging ? "bg-primary/5 border-primary" : ""}`}
|
||||
onDragOver={handleDragOver}
|
||||
onDragLeave={handleDragLeave}
|
||||
onDrop={handleDrop}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect, useRef } from "react";
|
||||
import { useCallback, useEffect, useRef } from "react";
|
||||
import { MessageBubble } from "./message-bubble";
|
||||
import { Loader2 } from "lucide-react";
|
||||
import type { UIMessage } from "ai";
|
||||
@@ -12,13 +12,32 @@ interface ChatMessagesProps {
|
||||
}
|
||||
|
||||
export function ChatMessages({ messages, isLoading, errorMessage }: ChatMessagesProps) {
|
||||
const scrollRef = useRef<HTMLDivElement>(null);
|
||||
const endRef = useRef<HTMLDivElement>(null);
|
||||
const shouldAutoScrollRef = useRef(true);
|
||||
const AUTO_SCROLL_THRESHOLD_PX = 96;
|
||||
|
||||
const updateShouldAutoScroll = useCallback(() => {
|
||||
const container = scrollRef.current;
|
||||
if (!container) return;
|
||||
|
||||
const distanceFromBottom =
|
||||
container.scrollHeight - container.scrollTop - container.clientHeight;
|
||||
shouldAutoScrollRef.current = distanceFromBottom <= AUTO_SCROLL_THRESHOLD_PX;
|
||||
}, []);
|
||||
|
||||
// Auto-scroll on new messages
|
||||
useEffect(() => {
|
||||
endRef.current?.scrollIntoView({ behavior: "smooth" });
|
||||
if (!shouldAutoScrollRef.current) return;
|
||||
endRef.current?.scrollIntoView({
|
||||
behavior: isLoading ? "auto" : "smooth",
|
||||
block: "end",
|
||||
});
|
||||
}, [messages, isLoading]);
|
||||
|
||||
useEffect(() => {
|
||||
updateShouldAutoScroll();
|
||||
}, [updateShouldAutoScroll]);
|
||||
|
||||
if (messages.length === 0 && !isLoading) {
|
||||
return (
|
||||
<div className="flex-1 flex items-center justify-center p-8">
|
||||
@@ -51,7 +70,11 @@ export function ChatMessages({ messages, isLoading, errorMessage }: ChatMessages
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex-1 overflow-y-auto px-4 md:px-6">
|
||||
<div
|
||||
ref={scrollRef}
|
||||
onScroll={updateShouldAutoScroll}
|
||||
className="flex-1 overflow-y-auto px-4 md:px-6"
|
||||
>
|
||||
<div className="max-w-3xl mx-auto py-4 space-y-1">
|
||||
{messages.map((message) => (
|
||||
<MessageBubble key={message.id} message={message} />
|
||||
|
||||
@@ -569,7 +569,7 @@ export function ChatPanel() {
|
||||
]);
|
||||
|
||||
return (
|
||||
<div className="flex flex-col h-full">
|
||||
<div className="flex h-full min-h-0 flex-col overflow-hidden">
|
||||
<ChatMessages messages={messages} isLoading={isLoading} errorMessage={chatError} />
|
||||
<ChatInput
|
||||
input={input}
|
||||
|
||||
Reference in New Issue
Block a user