useStickToBottom
設計時考慮了人工智慧聊天機器人,為 StackBlitz 的bolt.new
提供支持
一個輕量級的零依賴 React hook + 元件,可自動貼到容器底部並平滑地對內容進行動畫處理,以在添加新內容時保持其在螢幕上的視覺位置。
特徵 不需要 Safari 不支援的overflow-anchor
瀏覽器級 CSS 支援。 可以使用帶有 refs 的鉤子連接到任何現有組件。或簡單地使用提供的元件,它為您處理引用並提供上下文 - 因此子元件可以檢查isAtBottom
並以程式方式滾動到底部。 使用現代但受良好支援的ResizeObserver
API 來偵測內容何時調整大小。 正確處理滾動錨定。這就是當視窗上方的內容調整大小時,不會導致視窗中目前顯示的內容向上或向下跳躍。 允許用戶透過向上滾動隨時取消黏性。巧妙的邏輯將使用者捲動與自訂動畫滾動事件區分開來(不進行任何可能導致錯過某些事件的去抖動)。 行動裝置也可以很好地適應這種邏輯。 使用自訂實現的平滑滾動演算法,具有基於速度的彈簧動畫(具有可配置的參數)。其他庫使用帶有持續時間的緩動函數,但是當您想要以可變大小串流新內容時,這些函數效果不佳 - 這對於 AI 聊天機器人用例來說很常見。 scrollToBottom
回傳一個Promise
一旦捲動成功,它將解析為true
,如果滾動被取消,則解析為false
。
用法
組件
{messages.map((message) => (
))}
{/* This component uses `useStickToBottomContext` to scroll to bottom when the user enters a message */}
);
}
function ScrollToBottom() {
const { isAtBottom, scrollToBottom } = useStickToBottomContext();
return (
!isAtBottom && (
scrollToBottom()}
/>
)
);
}"> import { StickToBottom , useStickToBottomContext } from 'use-stick-to-bottom' ;
function Chat ( ) {
return (
< StickToBottom className = "h-[50vh] relative" resize = "smooth" initial = "smooth" >
< StickToBottom . Content className = "flex flex-col gap-4" >
{ messages . map ( ( message ) => (
< Message key = { message . id } message = { message } / >
) ) }
< / StickToBottom . Content >
< ScrollToBottom / >
{ /* This component uses `useStickToBottomContext` to scroll to bottom when the user enters a message */ }
< ChatBox / >
< / StickToBottom >
) ;
}
function ScrollToBottom ( ) {
const { isAtBottom , scrollToBottom } = useStickToBottomContext ( ) ;
return (
! isAtBottom && (
< button
className = "absolute i-ph-arrow-circle-down-fill text-4xl rounded-lg left-[50%] translate-x-[-50%] bottom-0"
onClick = { ( ) => scrollToBottom ( ) }
/ >
)
) ;
}
useStickToBottom
import { useStickToBottom } from 'use-stick-to-bottom' ;
function Component ( ) {
const { scrollRef , contentRef } = useStickToBottom ( ) ;
return (
< div style = { { overflow : 'auto' } } ref = { scrollRef } >
< div ref = { contentRef } >
{ messages . map ( ( message ) => (
< Message key = { message . id } message = { message } / >
) ) }
< / div >
< / div >
) ;
}