Skip to content

fix(tui): drop the abandoned ScrollBox remount key - #792

Merged
ericleepi314 merged 1 commit into
mainfrom
fix/tui-drop-abandoned-scrollbox-key
Aug 3, 2026
Merged

fix(tui): drop the abandoned ScrollBox remount key#792
ericleepi314 merged 1 commit into
mainfrom
fix/tui-drop-abandoned-scrollbox-key

Conversation

@ericleepi314

Copy link
Copy Markdown
Collaborator

Follow-up to #775. Removes a dead-end fix of mine that reached main by accident.

What happened

My first attempt at the resize-blanking bug keyed the transcript ScrollBox on cols, to force a fresh Yoga node on every width change. It worked on the repro, but the diagnosis behind it was wrong — the real cause is TranscriptScrollbar stretching the flex row from a stale viewportHeight, which #775 fixes at the source.

I abandoned the key, but it had already been swept into #774's d350b1a9, and that merged. So main currently carries both the real fix and the abandoned one.

Why it has to go

It isn't just redundant:

  • Orphaned subscriptions. Remounting the ScrollBox builds a new listenersRef Set behind useImperativeHandle(..., []), while the three useSyncExternalStore subscribers (useVirtualHistory, useViewportSnapshot, useScrollbarSnapshot) have stable deps and never resubscribe. Every subscription ends up on the dead handle — on every resize. fix(tui): stop the scrollbar from blanking the transcript on resize #775 added comments at those three call sites saying exactly this.
  • Cold start. The remount resets the handle, so getViewportHeight() returns 0 and useVirtualHistory takes its vp <= 0 branch: last 30 items only, behind a large blank topSpacer. On a long transcript that is worse than the bug being fixed.
  • The comment was wrong, which is worse than no comment — it told the next reader the vendored Yoga port fails to re-measure and that marking the tree dirty is insufficient. Neither is true; both were tested and ruled out.

Verification

🤖 Generated with Claude Code

An earlier attempt at the resize-blanking bug keyed the transcript ScrollBox on
`cols` to force a fresh Yoga node. It was abandoned once the real cause turned
out to be TranscriptScrollbar stretching the row from a stale viewportHeight
(fixed in #775), but it had already been swept into #774 and reached main.

It is not merely redundant now, it is harmful. Remounting the ScrollBox builds a
new listenersRef Set behind useImperativeHandle(..., []), while the three
useSyncExternalStore subscribers (useVirtualHistory, useViewportSnapshot,
useScrollbarSnapshot) have stable deps and never resubscribe — so every
subscription is orphaned on the dead handle, on every resize. It also resets the
handle, sending useVirtualHistory down its `vp <= 0` cold-start branch, which on
a long transcript mounts only the last 30 items behind a large blank topSpacer.

Its comment was also wrong about the mechanism, which is worse than no comment:
it told the next reader the vendored Yoga port fails to re-measure and that
marking the tree dirty is insufficient. Neither is true.

Verified the resize fix still holds without it: PTY at 60 -> 110 columns, blank
rows 7/30 before and after, matching #775's numbers. Suite unchanged from main's
baseline at 8 failed / 1681 passed across three runs.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown

Test Results

    1 files      1 suites   8m 14s ⏱️
9 675 tests 9 663 ✅ 12 💤 0 ❌
9 975 runs  9 963 ✅ 12 💤 0 ❌

Results for commit 00f88f2.

@ericleepi314
ericleepi314 merged commit 312d53d into main Aug 3, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant