Skip to content

fix(ui): pane follows the bottom and scrolls back (cursor-line model)#10

Merged
lavindeep merged 1 commit into
ui-reworkfrom
fix/ui-pane-autofollow-scroll
Jun 28, 2026
Merged

fix(ui): pane follows the bottom and scrolls back (cursor-line model)#10
lavindeep merged 1 commit into
ui-reworkfrom
fix/ui-pane-autofollow-scroll

Conversation

@lavindeep

Copy link
Copy Markdown
Owner

Found by the branch-4 live gate: a response taller than the pane stuck at the top — the newest streamed lines were hidden below the fold, and PageUp/PageDown did nothing.

Cause

The pane's FormattedTextControl has no cursor, so prompt_toolkit defaults UIContent.cursor_position to (0,0) and _scroll_without_linewrapping snaps vertical_scroll to keep that point visible every render — overriding any manual vertical_scroll the old _scroll_pane set.

Fix — cursor-line model

Expose the pane's intended line as the FTC cursor (get_cursor_position); pt scrolls to keep it visible regardless of focus:

  • Following (default): cursor on the last line → pane tracks the bottom, auto-scrolling as a response streams in.
  • PageUp: pins an earlier line (leaves follow mode) → a reader isn't yanked down when new output appends.
  • PageDown: moves toward the bottom; reaching it resumes following.

Pure _scroll_up/_scroll_down helpers hold the state math (5 new unit tests). Mouse-wheel scroll-back deferred to branch 9 (NOTE in code + DESIGN).

Verification

  • Gate green: ruff + mypy --strict, 1339 passed.
  • Live-verified on a real streaming gemma4:e4b turn: the pane tracked the streaming bottom (top + bottom both advanced through a 12-item response); PageUp scrolled back to the header/item 1; PageDown returned to the bottom and resumed follow.
  • DESIGN §31.12 corrected (the old 'wheel routes to the window under the cursor' claim was the bug).

The chat pane stuck to the top: a FormattedTextControl with no cursor
defaults to (0,0), and prompt_toolkit scrolls every render to keep that
point visible — overriding any manual vertical_scroll, so PageUp/PageDown
did nothing and a response taller than the pane hid its newest lines.

Drive the pane by exposing its cursor line instead. Following (the
default) puts the cursor on the last line, so pt keeps the bottom in view
and the pane auto-scrolls as a response streams in. PageUp pins an earlier
line (leaving follow mode, so a reader is not yanked down when output
appends); PageDown moves back toward the bottom and resumes following once
it gets there. The pure _scroll_up/_scroll_down helpers carry the state
math and are unit-tested; the live behavior (auto-follow + scroll-back)
was verified against a real streaming turn.

Mouse-wheel scroll-back is deferred to branch 9 (the wheel's vertical_scroll
is re-derived by the cursor-follow each render). DESIGN.md §31.12 updated.
@lavindeep lavindeep merged commit 1afb560 into ui-rework Jun 28, 2026
2 checks passed
@lavindeep lavindeep deleted the fix/ui-pane-autofollow-scroll branch June 28, 2026 00:58
lavindeep added a commit that referenced this pull request Jul 2, 2026
fix(ui): pane follows the bottom and scrolls back (cursor-line model)
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