fix(terminal): mobile scroll — horizontal overflow, scroll-to-bottom, touch-swipe, FitAddon clipping - #135
Open
mateusbellozupko wants to merge 4 commits into
Conversation
Mobile backgrounding (screen lock, app switch, flaky network) triggers frequent silent WS reconnects via the visibilitychange handler. Each reconnect re-fired session_joined, which force-scrolled the terminal to bottom and wiped out any manual scroll-up — making the terminal feel like it couldn't be scrolled. Now the forced scroll is skipped specifically on the silent-reconnect path, while genuine session opens/switches still land on latest output as intended. Ticket: 84e682fc-d8a6-4707-806e-5998412de5ed Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
CSS Overflow spec forces overflow-x: auto whenever overflow-y is non-visible, so the chat message list and xterm-viewport became independently scrollable/draggable regions on mobile whenever content was even slightly wider than the container. Adds explicit overflow-x: hidden plus word-break/overflow-wrap rules for long unbroken tokens (URLs, hashes, paths) in markdown content, while leaving <pre> code blocks free to scroll horizontally as intended. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
xterm.js v6's bundled scrollbar widget only wires mouse wheel and scrollbar dragging — no touch-pan support. Dispatches a synthetic wheel event on xterm's screen element from a vertical swipe gesture, reusing xterm's existing wheel pipeline (scrollback when present, SGR mouse-report forwarding to the CLI's alt-screen otherwise) instead of calling scrollLines() directly, which is a no-op with no scrollback. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…itAddon row clipping FitAddon._proposeGeometry() reads parentElement.clientHeight which per the CSS spec includes padding. The xterm mount div had px-4 py-3 directly on it, so FitAddon over-counted rows by ~24px / ~16px-per-row ≈ 1-2 rows. Those rows rendered but were clipped by the ancestor overflow-hidden, making the last 1-2 lines invisible on both desktop and mobile. Fix: padding moved to a wrapper div; containerRef is now a bare h-full w-full inner div so FitAddon measures the exact content area. Visual breathing room is preserved. ResizeObserver still targets containerRef (correct — it resizes with the wrapper). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Sorry @mateusbellozupko, you've used your own review budget of 250,000 diff characters for the last 7 days.
You can request another review in 1 day and 21 hours by commenting @sourcery-ai review. Upgrade to get a review now.
Reviewer's GuideImproves mobile terminal and chat usability by separating silent reconnect behavior from real opens, adding container-aware fitting and touch swipe scrolling, preventing unintended horizontal overflow, and fixing FitAddon row clipping through a padded wrapper and bare mount element. Sequence diagram for mobile terminal reconnect and scroll behaviorsequenceDiagram
participant Browser
participant AgentTerminal
participant WebSocket
participant XTerm
Browser->>AgentTerminal: visibilitychange
AgentTerminal->>AgentTerminal: setReconnectKey()
AgentTerminal->>WebSocket: connect and join session
WebSocket-->>AgentTerminal: session_joined
alt silent reconnect
AgentTerminal->>XTerm: preserve current scroll position
else real session open
AgentTerminal->>XTerm: scrollToBottom()
end
Sequence diagram for mobile terminal touch scrollingsequenceDiagram
actor User
participant TerminalMount
participant XTermScreen
participant XTermWheelPipeline
User->>TerminalMount: touchstart
User->>TerminalMount: touchmove
TerminalMount->>TerminalMount: determine vertical swipe after 10px threshold
TerminalMount->>XTermScreen: dispatch WheelEvent
XTermScreen->>XTermWheelPipeline: bubble wheel event
XTermWheelPipeline-->>XTermScreen: scroll scrollback or forward SGR mouse report
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
Author
|
@sourcery-ai review |
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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
Four related fixes for the terminal and chat experience on mobile (and partially desktop), applied as a batch:
fix(terminal): skip forced scroll-to-bottom on silent mobile reconnect — Mobile backgrounding (screen lock, app switch) triggers a silent WS reconnect via
visibilitychange. Each reconnect re-firedsession_joinedwhich force-scrolled to bottom, overriding any user scroll position. Now usesisSilentReconnectRefto distinguish silent reconnects from real session opens. Also addsResizeObserveron the container sofit()re-runs when the mobile browser's address bar collapses/expands.fix(chat): prevent horizontal scroll in chat/terminal on mobile — CSS Overflow spec forces
overflow-xto compute asautowheneveroverflow-yis non-visible. Added explicitoverflow-x: hiddenon the chat message div,.xterm-viewport { overflow-x: hidden !important }inindex.css, andoverflow-wrap: break-wordon.markdown-contentfor long unbroken tokens — while preservingoverflow-x: autoon<pre>code blocks.fix(terminal): wire touch-swipe scrolling for mobile xterm sessions — xterm.js v6's custom scroll widget only wires mouse wheel and scrollbar dragging, no touch events. Dispatches a synthetic
WheelEventon.xterm-screen(not the container — events bubble up) from a vertical swipe gesture, reusing xterm's existing wheel pipeline (scrollback when present, SGR mouse-report forwarding to the CLI's alt-screen otherwise). Direction disambiguation with 10px threshold;passive: falseonly ontouchmove.fix(terminal): separate padding wrapper from xterm mount div to fix FitAddon row clipping —
FitAddon._proposeGeometry()readsparentElement.clientHeightwhich per the CSS spec includes padding. The xterm mount div hadpx-4 py-3directly on it, causing FitAddon to over-count rows by ~1–2 (24px padding ÷ ~16px/row). Those rows rendered but were clipped by the ancestoroverflow-hidden, making the last lines invisible on both desktop and mobile. Padding moved to a wrapper div;containerRefis now a bareh-full w-fullinner div.Test plan
🤖 Generated with Claude Code
Summary by Sourcery
Improve mobile terminal and chat scrolling, sizing, and reconnect behavior without disrupting normal session navigation.
Bug Fixes:
Enhancements: