fix: tighten mobile keyboard layout — eliminate dead space and toolbar overlap

- Remove redundant 50px CSS padding on terminal-container when keyboard visible
- Reduce JS paddingBottom constant from +94 to +84 (exact toolbar + accessory)
- Add _shrinkPaddingToFit() to eliminate terminal row quantization gap
- Add CSS padding-bottom on .main for fixed toolbar clearance (keyboard hidden)
- Match iOS Safari toolbar offset (100vh - --app-height) in .main padding

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
arkon
2026-03-19 12:35:08 +01:00
co-authored by Claude Opus 4.6
parent 2491471ba5
commit 34c3d8f5ff
2 changed files with 48 additions and 7 deletions
+32 -1
View File
@@ -320,9 +320,10 @@ const KeyboardHandler = {
// Shrink main content area so terminal doesn't extend behind keyboard.
// Use stable keyboard height (not scroll-dependent) for padding.
// 84px = toolbar (40px) + accessory bar (44px).
const keyboardHeight = this.initialViewportHeight - (window.visualViewport.height || window.innerHeight);
if (main && keyboardHeight > 0) {
main.style.paddingBottom = `${keyboardHeight + 94}px`;
main.style.paddingBottom = `${keyboardHeight + 84}px`;
}
} else {
this.resetLayout();
@@ -369,6 +370,11 @@ const KeyboardHandler = {
try {
app.fitAddon.fit();
} catch {}
// Eliminate terminal row quantization gap: xterm can only show whole
// rows, so leftover pixels create dead space below the last row.
// Shrink .main's paddingBottom by the gap so the terminal fills flush
// to the accessory bar.
this._shrinkPaddingToFit();
app.terminal.scrollToBottom();
// Send resize to server so PTY dimensions match xterm
this._sendTerminalResize();
@@ -424,6 +430,31 @@ const KeyboardHandler = {
} catch {}
},
/**
* Shrink .main paddingBottom to eliminate the terminal row quantization gap.
* xterm can only render whole rows, so fractional-row pixels create dead
* space below the last row. After fitAddon.fit(), measure the gap and
* reduce padding by that amount so the terminal sits flush against the bars.
*/
_shrinkPaddingToFit() {
try {
const container = document.getElementById('terminalContainer');
const main = document.querySelector('.main');
if (!container || !main || typeof app === 'undefined' || !app.terminal) return;
const cellH = app.terminal._core?._renderService?.dimensions?.css?.cell?.height;
if (!cellH) return;
const gap = container.clientHeight - app.terminal.rows * cellH;
if (gap > 0 && gap < cellH) {
const currentPadding = parseInt(main.style.paddingBottom) || 0;
main.style.paddingBottom = currentPadding + gap + 'px';
if (app.fitAddon)
try {
app.fitAddon.fit();
} catch {}
}
} catch {}
},
/** Check if element is an input that triggers keyboard (excludes terminal) */
isInputElement(el) {
if (!el) return false;
+16 -6
View File
@@ -327,15 +327,27 @@ html.mobile-init .file-browser-panel {
max-height: calc(36px + var(--safe-area-top));
}
/* Add top margin to main content to account for fixed header */
/* Add top margin to main content to account for fixed header,
and bottom padding for the fixed toolbar (40px) so terminal
content doesn't extend behind it. JS overrides paddingBottom
when keyboard is visible, and resetLayout() clears the inline
style to re-expose this CSS value. */
.main {
margin-top: 42px;
padding-bottom: calc(40px + var(--safe-area-bottom));
}
.ios-device .main {
margin-top: calc(42px + var(--safe-area-top));
}
/* iOS Safari: toolbar is pushed up by (100vh - --app-height) to clear the
browser's bottom bar. Match that offset in main's padding so the terminal
doesn't extend behind the toolbar. */
.ios-device.safari-browser .main {
padding-bottom: calc(40px + var(--safe-area-bottom) + (100vh - var(--app-height, 100vh)));
}
.header-right {
padding-left: 0.2rem;
gap: 0.1rem;
@@ -1586,11 +1598,9 @@ html.mobile-init .file-browser-panel {
scroll-margin-top: 80px;
}
/* When keyboard is visible, adjust content to account for moved toolbar */
.keyboard-visible .terminal-container {
/* Reduce terminal height when keyboard is up so it doesn't overlap toolbar */
padding-bottom: 50px;
}
/* When keyboard is visible, the JS paddingBottom on .main already reserves
space for toolbar + accessory bar. No extra padding needed here — it was
double-counting and creating dead space between terminal and the bars. */
/* Ensure modals scroll properly when keyboard is visible */
.keyboard-visible .modal-body {