fix: route mobile terminal swipes to the terminal, not the page layout
- Add touch-action: none and overscroll-behavior: none to mobile terminal
page, content, wrapper, container, and xterm viewport so the browser
never treats swipes as page/address-bar scrolling or pull-to-refresh.
- Make .terminal-page.mobile fixed-position to prevent viewport layout
scroll; keep the overlay toolbar as absolute with pointer-events only
on interactive parts.
- Rework the mobile touch handler in terminal.tsx:
* Detect normal vs alternate buffer via term.buffer.active.type instead
of measuring the DOM viewport, which was unreliable in tmux/vim.
* Accumulate swipe distance and emit SGR 1006 mouse-wheel sequences in
steps, so tmux pane scrolling tracks the gesture correctly.
* Prevent default as soon as the swipe is recognized so the page does
not start a competing scroll gesture.
Quality gates: npm run typecheck, npm run lint clean, npm test -- --run 87 passed.
This commit is contained in:
@@ -551,6 +551,14 @@ a.nav-item,
|
||||
height: 100%;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
touch-action: none;
|
||||
overscroll-behavior: none;
|
||||
}
|
||||
|
||||
/* Ensure xterm's internal viewport also disables browser gestures on mobile */
|
||||
.terminal-container .xterm-viewport {
|
||||
touch-action: none;
|
||||
overscroll-behavior: none;
|
||||
}
|
||||
|
||||
/* xterm.js manages its own positioning and sizing */
|
||||
@@ -564,6 +572,13 @@ a.nav-item,
|
||||
/* Mobile terminal container - no padding to maximize space */
|
||||
.terminal-wrapper.mobile .terminal-container {
|
||||
padding: 0;
|
||||
touch-action: none;
|
||||
overscroll-behavior: none;
|
||||
}
|
||||
|
||||
.terminal-wrapper.mobile {
|
||||
touch-action: none;
|
||||
overscroll-behavior: none;
|
||||
}
|
||||
|
||||
/* Ensure xterm viewport fills container properly */
|
||||
@@ -855,17 +870,23 @@ a.nav-item,
|
||||
Mobile Terminal Overlay
|
||||
============================================ */
|
||||
|
||||
/* Mobile terminal page — no padding, terminal fills viewport */
|
||||
/* Mobile terminal page — no padding, terminal fills viewport, locked in place */
|
||||
.terminal-page.mobile {
|
||||
padding: 0;
|
||||
gap: 0;
|
||||
height: 100vh;
|
||||
height: 100dvh;
|
||||
position: relative;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
overflow: hidden;
|
||||
touch-action: none;
|
||||
overscroll-behavior: none;
|
||||
}
|
||||
|
||||
/* Overlay status bar — floats over terminal, never resizes it */
|
||||
/* Overlay status bar — floats over terminal; only its buttons consume pointer events */
|
||||
.mobile-terminal-overlay {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
@@ -874,11 +895,21 @@ a.nav-item,
|
||||
z-index: 100;
|
||||
background: #2d2d2d;
|
||||
border-bottom: 1px solid #3e3e3e;
|
||||
pointer-events: none;
|
||||
transition:
|
||||
transform 0.3s ease,
|
||||
opacity 0.3s ease;
|
||||
}
|
||||
|
||||
.mobile-terminal-overlay.visible {
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
.mobile-terminal-overlay > *,
|
||||
.mobile-terminal-overlay-tabs {
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
.mobile-terminal-overlay.hidden {
|
||||
transform: translateY(-100%);
|
||||
opacity: 0;
|
||||
@@ -978,13 +1009,15 @@ a.nav-item,
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
/* Terminal content — always fills full viewport on mobile */
|
||||
/* Terminal content — always fills full viewport on mobile, locked against page scroll */
|
||||
.terminal-page-content.mobile-full {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
overflow: hidden;
|
||||
touch-action: none;
|
||||
overscroll-behavior: none;
|
||||
}
|
||||
|
||||
/* Mobile fullscreen */
|
||||
|
||||
Reference in New Issue
Block a user