Auto Scroll
Keep the chat scrolled to the bottom during streaming.
useAutoScroll keeps your scroll container pinned to the bottom as new content streams in.
Basic Usage
import { useStreamChat, useAutoScroll } from "@deltakit/react";
function Chat() {
const { messages, sendMessage } = useStreamChat({ api: "/api/chat" });
const { ref, scrollToBottom, isAtBottom } = useAutoScroll([messages]);
return (
<div className="flex h-screen flex-col">
<div ref={ref} className="flex-1 overflow-y-auto">
{messages.map((msg) => (
<div key={msg.id}>
<strong>{msg.role}:</strong>{" "}
{msg.parts
.filter((p) => p.type === "text")
.map((p) => p.text)
.join("")}
</div>
))}
</div>
<form
onSubmit={(e) => {
e.preventDefault();
const input = e.currentTarget.elements.namedItem(
"message",
) as HTMLInputElement;
if (!input.value.trim()) return;
sendMessage(input.value);
scrollToBottom();
input.value = "";
}}
>
<input name="message" placeholder="Type a message..." />
<button type="submit">Send</button>
</form>
</div>
);
}How It Works
The hook tracks whether the user is near the bottom of the scroll container:
- Pinned (default) — as content grows, the view stays at the bottom.
- Detached — when the user scrolls up, or wheels upward during active pinning, auto-scroll disengages so they can read earlier messages undisturbed.
- Re-pinned — when the user scrolls back near the bottom (within
thresholdpixels), auto-scroll re-engages automatically.
Internally the hook uses a MutationObserver and ResizeObserver, so it catches content changes during streaming even between React re-renders (e.g. DOM mutations from markdown renderers).
Scroll to Bottom on Send
The hook does not automatically scroll when a new user message is sent — it only reacts to scroll position. Call scrollToBottom() in your submit handler to re-pin:
const handleSubmit = (text: string) => {
sendMessage(text);
scrollToBottom();
};Disabling Auto Scroll
Pass enabled: false to turn off auto-scroll while keeping the ref attached:
const { ref } = useAutoScroll([messages], { enabled: false });Smooth Scrolling
During streaming, the hook keeps the viewport pinned using instant scrollTop updates to avoid flicker from overlapping smooth-scroll animations. The behavior option controls only the explicit scrollToBottom() call — use "smooth" (default) for an animated jump back, or "instant" to snap immediately:
const { ref, scrollToBottom } = useAutoScroll([messages], { behavior: "smooth" });Recipes
For common auto-scroll patterns, see these recipes:
- Scroll to Bottom Indicator — Show a button when users scroll up
API Reference
See useAutoScroll API Reference for full options and return values.