Assistant: scroll the thread to a new reply for real
Build image / build-and-push (push) Successful in 20s
Gadfly review (reusable) / review (pull_request) Successful in 2m2s
Adversarial Review (Gadfly) / review (pull_request) Successful in 2m3s

scrollIntoView({ behavior: 'smooth' }) on the thread's nested scroller never
moved it in Chrome — measured live: scrollTop stayed 0 after sending and
after the reply, while the instant form scrolled to the end. A long
conversation therefore showed its oldest messages after every turn, with
the new reply out of view below. Instant it is.

Co-Authored-By: Claude Fable 5 <[email protected]>
This commit is contained in:
2026-08-23 03:02:50 -04:00
co-authored by Claude Fable 5
parent 0aabccf1bd
commit e184ae5565
+5 -1
View File
@@ -40,8 +40,12 @@ export function AssistantTab({ gardenId, canEdit, undo, large = false }: { garde
// Deliberately NOT aborted on unmount: selecting a bed switches the rail to // Deliberately NOT aborted on unmount: selecting a bed switches the rail to
// the inspector, and that must not kill a turn mid-flight. The request runs // the inspector, and that must not kill a turn mid-flight. The request runs
// on; the exchange is persisted server-side; coming back shows it. // on; the exchange is persisted server-side; coming back shows it.
// Instant, not smooth: Chrome left the thread at the top with
// `behavior: 'smooth'` — a smooth scrollIntoView into this nested scroller
// never moved it, so every new reply landed out of view below a long
// conversation (found live, 2026-08-23). The instant form scrolls.
useEffect(() => { useEffect(() => {
bottom.current?.scrollIntoView({ behavior: 'smooth', block: 'end' }) bottom.current?.scrollIntoView({ block: 'end' })
}, [history.data, pending]) }, [history.data, pending])
const send = () => { const send = () => {