feat: add floating scroll-to-bottom button#701
Conversation
Show a floating ↓ button when the user scrolls up away from the latest messages. Clicking it smooth-scrolls to the bottom and re-engages auto-scroll. Changes: - useChatScroll: expose isScrolledUp state and scrollToBottomNow() imperative action alongside existing containerRef/bottomRef - Chat: render .chat-scroll-bottom button (sticky, centered) when isScrolledUp, using ArrowDown icon from lucide-react - main.css: .chat-messages gets position:relative, .chat-scroll-bottom is a 36px circle with shadow and hover lift - i18n: add scrollToBottom string to all 10 locales
| const scrollToBottomNow = useCallback(() => { | ||
| userScrolledUpRef.current = false; | ||
| setIsScrolledUp(false); | ||
| bottomRef.current?.scrollIntoView({ behavior: "smooth" }); | ||
| }, []); |
There was a problem hiding this comment.
Smooth scroll fires intermediate events that re-engage scrolled-up state
scrollToBottomNow sets userScrolledUpRef.current = false and setIsScrolledUp(false), then immediately kicks off a behavior: "smooth" scroll. The smooth animation generates a continuous stream of scroll events as the container travels from its current position to the bottom. Each intermediate event calls handleScroll, which evaluates atBottom = scrollHeight - scrollTop - clientHeight < 60 — a check that returns false for most of the animation. This causes setIsScrolledUp(true) and userScrolledUpRef.current = true to fire repeatedly mid-animation: the button flashes back into view and auto-scroll is paused again the instant the user clicks it.
The simplest fix is to use instant scrolling in scrollToBottomNow so no intermediate events are generated. Direct assignment to scrollTop is cleaner than scrollIntoView here because it operates on the container you already have a ref to. Alternatively, keep scrollIntoView but guard handleScroll with an isProgrammaticScrollRef flag that is set before the call and cleared in a short setTimeout.
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
Feature
Show a floating scroll-to-bottom button (↓) when the user scrolls up away from the latest messages. Clicking it smooth-scrolls back to the bottom and re-engages auto-scroll for new messages.
Changes
useChatScroll.ts
isScrolledUp: booleanto the return type — updated via scroll event listenerscrollToBottomNow()imperative action — resets scrolled-up state and scrolls to bottomuseStatealongside the existing ref so React knows when to show/hide the buttonChat.tsx
isScrolledUpandscrollToBottomNowfromuseChatScroll.chat-scroll-bottombutton (withArrowDownicon) whenisScrolledUpis truemain.css
.chat-messagesnow hasposition: relativeso the sticky button anchors correctly.chat-scroll-bottom— 36x36px circle, sticky at bottom, with box-shadow, hover lift effecti18n
scrollToBottomkey to all 10 supported locales