fix: scroll-up while ai is generating content
- added a scroll-to-bottom button - users can now scroll-up while generating content
This commit is contained in:
parent
a25097108d
commit
d87f818241
@ -1,6 +1,6 @@
|
|||||||
import { useSocket } from "@/context/SocketContext"
|
import { useSocket } from "@/context/SocketContext"
|
||||||
import { TFile } from "@/lib/types"
|
import { TFile } from "@/lib/types"
|
||||||
import { X } from "lucide-react"
|
import { X, ChevronDown } from "lucide-react"
|
||||||
import { nanoid } from "nanoid"
|
import { nanoid } from "nanoid"
|
||||||
import { useEffect, useRef, useState } from "react"
|
import { useEffect, useRef, useState } from "react"
|
||||||
import LoadingDots from "../../ui/LoadingDots"
|
import LoadingDots from "../../ui/LoadingDots"
|
||||||
@ -38,23 +38,47 @@ export default function AIChat({
|
|||||||
// Initialize textarea ref
|
// Initialize textarea ref
|
||||||
const textareaRef = useRef<HTMLTextAreaElement>(null)
|
const textareaRef = useRef<HTMLTextAreaElement>(null)
|
||||||
|
|
||||||
// Scroll to bottom of chat when messages change
|
// state variables for auto scroll and scroll button
|
||||||
useEffect(() => {
|
const [autoScroll, setAutoScroll] = useState(true)
|
||||||
scrollToBottom()
|
const [showScrollButton, setShowScrollButton] = useState(false)
|
||||||
}, [messages])
|
|
||||||
|
|
||||||
// Scroll to bottom of chat when messages change
|
// scroll to bottom of chat when messages change
|
||||||
const scrollToBottom = () => {
|
useEffect(() => {
|
||||||
if (chatContainerRef.current) {
|
if (autoScroll) {
|
||||||
setTimeout(() => {
|
scrollToBottom()
|
||||||
chatContainerRef.current?.scrollTo({
|
|
||||||
top: chatContainerRef.current.scrollHeight,
|
|
||||||
behavior: "smooth",
|
|
||||||
})
|
|
||||||
}, 100)
|
|
||||||
}
|
}
|
||||||
|
}, [messages, autoScroll])
|
||||||
|
|
||||||
|
// scroll to bottom of chat when messages change
|
||||||
|
const scrollToBottom = (force: boolean = false) => {
|
||||||
|
if (!chatContainerRef.current || (!autoScroll && !force)) return
|
||||||
|
|
||||||
|
chatContainerRef.current.scrollTo({
|
||||||
|
top: chatContainerRef.current.scrollHeight,
|
||||||
|
behavior: force ? "smooth" : "auto",
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// function to handle scroll events
|
||||||
|
const handleScroll = () => {
|
||||||
|
if (!chatContainerRef.current) return
|
||||||
|
|
||||||
|
const { scrollTop, scrollHeight, clientHeight } = chatContainerRef.current
|
||||||
|
const isAtBottom = Math.abs(scrollHeight - scrollTop - clientHeight) < 50
|
||||||
|
|
||||||
|
setAutoScroll(isAtBottom)
|
||||||
|
setShowScrollButton(!isAtBottom)
|
||||||
|
}
|
||||||
|
|
||||||
|
// scroll event listener
|
||||||
|
useEffect(() => {
|
||||||
|
const container = chatContainerRef.current
|
||||||
|
if (container) {
|
||||||
|
container.addEventListener('scroll', handleScroll)
|
||||||
|
return () => container.removeEventListener('scroll', handleScroll)
|
||||||
|
}
|
||||||
|
}, [])
|
||||||
|
|
||||||
// Add context tab to context tabs
|
// Add context tab to context tabs
|
||||||
const addContextTab = (
|
const addContextTab = (
|
||||||
type: string,
|
type: string,
|
||||||
@ -160,7 +184,7 @@ export default function AIChat({
|
|||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
ref={chatContainerRef}
|
ref={chatContainerRef}
|
||||||
className="flex-grow overflow-y-auto p-4 space-y-4"
|
className="flex-grow overflow-y-auto p-4 space-y-4 relative"
|
||||||
>
|
>
|
||||||
{messages.map((message, messageIndex) => (
|
{messages.map((message, messageIndex) => (
|
||||||
// Render chat message component for each message
|
// Render chat message component for each message
|
||||||
@ -173,6 +197,17 @@ export default function AIChat({
|
|||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
{isLoading && <LoadingDots />}
|
{isLoading && <LoadingDots />}
|
||||||
|
|
||||||
|
{/* Add scroll to bottom button */}
|
||||||
|
{showScrollButton && (
|
||||||
|
<button
|
||||||
|
onClick={() => scrollToBottom(true)}
|
||||||
|
className="fixed bottom-36 right-6 bg-primary text-primary-foreground rounded-md border border-primary p-0.5 shadow-lg hover:bg-primary/90 transition-all"
|
||||||
|
aria-label="Scroll to bottom"
|
||||||
|
>
|
||||||
|
<ChevronDown className="h-5 w-5" />
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="p-4 border-t mb-14">
|
<div className="p-4 border-t mb-14">
|
||||||
{/* Render context tabs component */}
|
{/* Render context tabs component */}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user