You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Fixes wrapped lines overlapping in the virtualized Code.Viewer (workflow editor terminal Output/Input panel) — reported in Slack with a wrapped conversationId line drawing over the row below it
Root cause: the re-measure effect called virtualizer.measure() on every visibleLines identity change. TanStack Virtual's measure() wipes the size cache without re-measuring mounted rows — ResizeObserver only fires on size changes and React never re-invokes an unchanged measureElement ref — so any content change that keeps row heights (Prism finishing its lazy load right after first open, search-highlight <mark> wrapping) permanently collapsed every wrapped row to the 21px estimate
The wipe now runs only when leaving wrap mode, the one transition that needs it: refs detach with wrapped heights still cached, and falling back to the fixed estimate is exactly correct for nowrap. Entering wrap re-measures as refs attach, and genuine height changes are caught by the per-row ResizeObserver, so no other trigger is needed (this also removes a redundant mount-time wipe + re-measure pass)
Type of Change
Bug fix
Testing
Reproduced deterministically in an isolated Playwright harness rendering Code.Viewer with virtualized + wrapText: before the fix, a height-preserving content change left rows at translateY(0/21/42…) while wrapped rows measured taller (overlap); after, every row's offset equals the cumulative measured heights. Ran a 12-scenario matrix (prism lazy-load, search set/clear, JSON collapse toggle on/off, content change both directions, width narrow/restore, wrap off/on, search after wrap cycle): original code fails 8/12 with overlap, fixed code passes 12/12 including every scenario the original passed. Typecheck (emcn + sim) and biome clean.
Low Risk
Single, targeted change to virtualizer measurement timing in code.tsx with no auth, data, or API impact.
Overview
Fixes wrapped line overlap in virtualized Code.Viewer (e.g. workflow terminal Output/Input) by changing when TanStack Virtual’s row size cache is cleared.
The re-measure useEffect no longer depends on visibleLines or calls virtualizer.measure() on every content update. measure() now runs only when wrapText becomes false, so cached wrapped heights are dropped when leaving wrap mode and fixed 21px estimates apply for nowrap. Entering wrap and height-preserving updates (Prism lazy load, search <mark> highlights) rely on measureElement refs and per-row ResizeObserver instead of a global cache wipe that left mounted rows stuck at the estimate.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Code.Viewer(workflow editor terminal Output/Input panel) — reported in Slack with a wrappedconversationIdline drawing over the row below itvirtualizer.measure()on everyvisibleLinesidentity change. TanStack Virtual'smeasure()wipes the size cache without re-measuring mounted rows — ResizeObserver only fires on size changes and React never re-invokes an unchangedmeasureElementref — so any content change that keeps row heights (Prism finishing its lazy load right after first open, search-highlight<mark>wrapping) permanently collapsed every wrapped row to the 21px estimateType of Change
Testing
Reproduced deterministically in an isolated Playwright harness rendering
Code.Viewerwithvirtualized+wrapText: before the fix, a height-preserving content change left rows attranslateY(0/21/42…)while wrapped rows measured taller (overlap); after, every row's offset equals the cumulative measured heights. Ran a 12-scenario matrix (prism lazy-load, search set/clear, JSON collapse toggle on/off, content change both directions, width narrow/restore, wrap off/on, search after wrap cycle): original code fails 8/12 with overlap, fixed code passes 12/12 including every scenario the original passed. Typecheck (emcn + sim) and biome clean.Checklist