useStickToBottom
ออกแบบโดยคำนึงถึงบอทแชท AI เป็นหลัก ขับเคลื่อน bolt.new
โดย StackBlitz
React hook + Component น้ำหนักเบา ที่ไม่ต้องพึ่งพิงใด ๆ ซึ่งจะเกาะที่ด้านล่างของคอนเทนเนอร์โดยอัตโนมัติ และเคลื่อนไหวเนื้อหาได้อย่างราบรื่นเพื่อรักษาตำแหน่งที่มองเห็นได้บนหน้าจอในขณะที่มีการเพิ่มเนื้อหาใหม่
คุณสมบัติ ไม่ต้องการการรองรับ CSS ระดับเบราว์เซอร์ overflow-anchor
ซึ่ง Safari ไม่รองรับ สามารถเชื่อมต่อกับส่วนประกอบที่มีอยู่ได้โดยใช้ตะขอที่มีการอ้างอิง หรือเพียงแค่ใช้ส่วนประกอบที่ให้มา ซึ่งจัดการการอ้างอิงสำหรับคุณ พร้อมทั้งให้บริบท ดังนั้นส่วนประกอบลูกจึงสามารถตรวจสอบ isAtBottom
และเลื่อนไปทางด้านล่างโดยทางโปรแกรม ใช้ ResizeObserver
API ที่ทันสมัยแต่ได้รับการสนับสนุนอย่างดีเพื่อตรวจจับเมื่อเนื้อหาปรับขนาด รองรับเนื้อหาที่หดตัวโดยไม่สูญเสียความเหนียว - ไม่ใช่แค่สูงขึ้น จัดการ Scroll Anchoring ได้อย่างถูกต้อง นี่คือจุดที่เมื่อเนื้อหาเหนือวิวพอร์ตปรับขนาด ซึ่งจะไม่ทำให้เนื้อหาที่แสดงในวิวพอร์ตปัจจุบันกระโดดขึ้นหรือลง ให้ผู้ใช้สามารถยกเลิกการติดได้ตลอดเวลาโดยเลื่อนขึ้น ตรรกะที่ชาญฉลาดจะแยกแยะผู้ใช้ที่เลื่อนออกจากเหตุการณ์การเลื่อนภาพเคลื่อนไหวที่กำหนดเอง (โดยไม่ทำการดีเด้งใดๆ ซึ่งอาจทำให้พลาดเหตุการณ์บางอย่างได้) อุปกรณ์เคลื่อนที่ก็ทำงานได้ดีกับตรรกะนี้เช่นกัน ใช้อัลกอริธึมการเลื่อนที่ราบรื่นแบบกำหนดเองซึ่งมีภาพเคลื่อนไหวสปริงตามความเร็ว (พร้อมพารามิเตอร์ที่กำหนดค่าได้) ไลบรารีอื่นๆ ใช้ฟังก์ชันการค่อยๆ เปลี่ยนที่มีระยะเวลาแทน แต่สิ่งเหล่านี้ทำงานได้ไม่ดีนักเมื่อคุณต้องการสตรีมเนื้อหาใหม่ที่มีการปรับขนาดที่หลากหลาย ซึ่งเป็นเรื่องปกติสำหรับกรณีการใช้งานแชทบอท 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
ตะขอ StickToBottom 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 >
) ;
}