From 982a425162abe1f787ed3fb27013bba5544d1800 Mon Sep 17 00:00:00 2001 From: Brooklyn Nicholson Date: Sun, 26 Jul 2026 00:20:49 -0500 Subject: [PATCH] perf(desktop): skip the timeline rect walk while following the bottom MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ThreadTimeline's scroll compute read getBoundingClientRect for every user message per scroll frame; interleaved with React's streaming style writes each read forced a full reflow — the hottest self-time frame in the multitab profile (620ms over one 5-tab run). While the viewport is pinned to the bottom the active prompt is simply the last entry, so answer from data and save the layout reads for actual scrollback. --- .../src/components/assistant-ui/thread/timeline.tsx | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/apps/desktop/src/components/assistant-ui/thread/timeline.tsx b/apps/desktop/src/components/assistant-ui/thread/timeline.tsx index b1603076e5f..df2a4c7332c 100644 --- a/apps/desktop/src/components/assistant-ui/thread/timeline.tsx +++ b/apps/desktop/src/components/assistant-ui/thread/timeline.tsx @@ -196,6 +196,17 @@ export const ThreadTimeline: FC = () => { const compute = () => { raf = 0 + // Pinned to the bottom (the entire streaming steady-state): the active + // prompt is simply the last one. Skipping the walk matters — it reads a + // rect per user message per scroll frame, and interleaved with React's + // streaming style writes each read forces a full reflow (the single + // hottest frame in the multitab profile). + if (viewport.dataset.following === 'true') { + setActiveIndex(prev => (prev === entries.length - 1 ? prev : entries.length - 1)) + + return + } + const top = viewport.getBoundingClientRect().top const offsets = entries.map(entry => {