graph: session deep links reliably jump to the source message

The mount-time jump never fired on real graph-link arrivals: the
transcript scroller's ref is attached by a later sibling, and the queued
rAF was cancelled outright whenever use-stick-to-bottom re-created its
context while the initial scroll settled — every link landed at the
bottom (owner report 2026-10-13).

Rewrite the mount path as a synchronous 64ms retry watcher that keeps
running past its first success (hydration/adoption can replace the
jumped-to node), with a ~20s watchdog for cold-compile SSR streams
(observed 6.8s). jump() now reads the stick-to-bottom context through a
ref so effect identities stay stable, and the unmount cleanup no longer
strips a live flash. Verified live on real data: full load, SPA link
navigation, and in-session hashchange all land the anchor 16px from the
scroller top with the 2s highlight.

Also gives the node card's session/file rows matching horizontal and
vertical padding (px-2 py-1.5).
This commit is contained in:
amosblomqvist
2026-10-13 09:28:09 +03:00
parent cdd8ac047e
commit 2a8f65de6e
3 changed files with 59 additions and 33 deletions
+1 -1
View File
@@ -1313,7 +1313,7 @@ export function Chat({
<SessionFind scopeRef={sessionFindScopeRef} scrollContextRef={scrollContextRef} />
<div ref={sessionFindScopeRef} className="relative flex min-h-0 flex-1">
<Conversation className="h-full min-w-0 flex-1" initial="instant" contextRef={scrollContextRef}>
<SessionMessageNavigation messages={messages} />
<SessionMessageNavigation />
<ConversationContent className="min-h-full gap-0 p-0">
<div data-session-find-root="" className={`${COLUMN} flex flex-1 flex-col gap-4 pt-4`}>
{messages.length === 0 && !busy && (