feat: implement auto scroll

This commit is contained in:
shadcn 2023-06-15 15:27:41 +04:00
parent a9993640ff
commit b8d3ba85f5
6 changed files with 71 additions and 17 deletions

View file

@ -3,26 +3,12 @@
import * as React from 'react'
import { cn } from '@/lib/utils'
import { useAtBottom } from '@/lib/hooks/use-at-bottom'
import { Button, type ButtonProps } from '@/components/ui/button'
import { IconArrowDown } from '@/components/ui/icons'
export function ButtonScrollToBottom({ className, ...props }: ButtonProps) {
const [isAtBottom, setIsAtBottom] = React.useState(false)
React.useEffect(() => {
const handleScroll = () => {
setIsAtBottom(
window.innerHeight + window.scrollY > document.body.offsetHeight - 100
)
}
window.addEventListener('scroll', handleScroll, { passive: true })
handleScroll()
return () => {
window.removeEventListener('scroll', handleScroll)
}
}, [])
const isAtBottom = useAtBottom()
return (
<Button

View file

@ -0,0 +1,29 @@
'use client'
import * as React from 'react'
import { useInView } from 'react-intersection-observer'
import { useAtBottom } from '@/lib/hooks/use-at-bottom'
interface ChatScrollAnchorProps {
trackVisibility?: boolean
}
export function ChatScrollAnchor({ trackVisibility }: ChatScrollAnchorProps) {
const isAtBottom = useAtBottom()
const { ref, entry, inView } = useInView({
trackVisibility,
delay: 100,
rootMargin: '0px 0px -150px 0px'
})
React.useEffect(() => {
if (isAtBottom && trackVisibility && !inView) {
entry?.target.scrollIntoView({
block: 'start'
})
}
}, [inView, entry, isAtBottom, trackVisibility])
return <div ref={ref} className="h-px w-full" />
}

View file

@ -6,6 +6,7 @@ import { cn } from '@/lib/utils'
import { ChatList } from '@/components/chat-list'
import { ChatPanel } from '@/components/chat-panel'
import { EmptyScreen } from '@/components/empty-screen'
import { ChatScrollAnchor } from '@/components/chat-scroll-anchor'
export interface ChatProps extends React.ComponentProps<'div'> {
initialMessages?: Message[]
@ -26,7 +27,10 @@ export function Chat({ id, initialMessages, className }: ChatProps) {
<>
<div className={cn('pb-[200px] pt-4 md:pt-10', className)}>
{messages.length ? (
<ChatList messages={messages} />
<>
<ChatList messages={messages} />
<ChatScrollAnchor trackVisibility={isLoading} />
</>
) : (
<EmptyScreen setInput={setInput} />
)}