diff --git a/frontend/src/components/chat/ChatPanel.tsx b/frontend/src/components/chat/ChatPanel.tsx index ebce580..aa1653e 100644 --- a/frontend/src/components/chat/ChatPanel.tsx +++ b/frontend/src/components/chat/ChatPanel.tsx @@ -17,17 +17,17 @@ import { Textarea } from "@/components/ui/textarea"; import MessageBubble from "./MessageBubble"; import SourceCard from "./SourceCard"; import { - Send, - Loader2, - Trash2, - MessageSquare, - Download, - Mic, - MicOff, - HelpCircle, -} from "lucide-react"; -import { cn } from "@/lib/utils"; - + Send, + Loader2, + Trash2, + MessageSquare, + Download, + Mic, + MicOff, + HelpCircle, + ChevronDown, + } from "lucide-react"; + import { cn } from "@/lib/utils"; interface ISpeechRecognitionEvent { resultIndex: number; results: { @@ -96,11 +96,13 @@ export default function ChatPanel({ activeDoc, onCitationClick }: Props) { // New State for Keyboard Shortcuts Help Modal const [showHelpModal, setShowHelpModal] = useState(false); + const [showScrollButton, setShowScrollButton] = useState(false); const recognitionRef = useRef(null); const initialInputRef = useRef(""); const textareaRef = useRef(null); const bottomRef = useRef(null); + const containerRef = useRef(null); const prevDocId = useRef(null); const exportMenuRef = useRef(null); const abortControllerRef = useRef(null); @@ -125,9 +127,28 @@ export default function ChatPanel({ activeDoc, onCitationClick }: Props) { // Auto-scroll to bottom whenever messages change useEffect(() => { - bottomRef.current?.scrollIntoView({ behavior: "smooth" }); + if (containerRef.current) { + const { scrollHeight, scrollTop, clientHeight } = containerRef.current; + if (scrollHeight - scrollTop - clientHeight < 150) { + bottomRef.current?.scrollIntoView({ behavior: "smooth" }); + } + } else { + bottomRef.current?.scrollIntoView({ behavior: "smooth" }); + } }, [messages]); + const handleScroll = () => { + if (!containerRef.current) return; + const { scrollTop, scrollHeight, clientHeight } = containerRef.current; + setShowScrollButton(scrollTop < scrollHeight - clientHeight - 100); + }; + + const scrollToBottom = () => { + if (containerRef.current) { + containerRef.current.scrollTo({ top: containerRef.current.scrollHeight, behavior: "smooth" }); + } + }; + useEffect(() => { return () => { resetChat(); @@ -598,8 +619,10 @@ export default function ChatPanel({ activeDoc, onCitationClick }: Props) { return (
{/* ── Chat Messages ──────────────────────────── */} -
{historyLoading ? ( @@ -674,6 +697,19 @@ export default function ChatPanel({ activeDoc, onCitationClick }: Props) {
+ {/* Scroll to bottom button */} + + {/* ── Input Area ─────────────────────────────── */}