fix(maestro): hide mobile key bar when keyboard is dismissed while focused
ci / rust (push) Successful in 5m29s

Focus alone was the wrong signal: dismissing the soft keyboard (e.g. Android
back button) keeps the terminal focused, so the key bar lingered. Detect the
keyboard's actual visibility from the visual-viewport shrink — while an editable
element is focused, a height past a threshold below the focus-free baseline
means the keyboard is up — and gate the bar on a new `html.kb-open` class in
addition to the per-terminal focus class.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-20 21:04:15 +00:00
co-authored by Claude Opus 4.8
parent 6b0c92265e
commit 1006651fb4
2 changed files with 30 additions and 3 deletions
+6 -3
View File
@@ -1192,10 +1192,13 @@ textarea {
background: var(--surface);
}
/* Shown on touch only while the terminal is focused (soft keyboard up) — the
`keybar-active` class is toggled on textarea focus/blur in attach.ts. */
/* Shown on touch only while *this* terminal is focused (`keybar-active`, toggled
on textarea focus/blur in attach.ts) AND the soft keyboard is actually up
(`html.kb-open`, detected from the visual-viewport shrink in viewport.ts).
Both are needed: dismissing the keyboard doesn't blur the terminal, so focus
alone would leave the bar lingering. */
@media (pointer: coarse) {
.attach-keybar.keybar-active {
html.kb-open .attach-keybar.keybar-active {
display: grid;
}
}
+24
View File
@@ -19,18 +19,42 @@
* it, where offsetTop stays non-zero.)
*
* No-ops where `visualViewport` is unavailable; the CSS falls back to `100%`.
*
* It also toggles an `html.kb-open` class that reflects whether the soft
* keyboard is actually up, used to gate the mobile key bar. Focus is the wrong
* signal: dismissing the keyboard (e.g. the Android back button) keeps the
* terminal focused, so the bar would linger. Instead we watch the visual
* viewport shrink: while an editable element is focused, a height noticeably
* below the tallest height seen with nothing focused means the keyboard is open.
* The baseline resets whenever nothing is being edited, so it self-corrects
* across orientation changes and URL-bar collapse.
*/
const KB_OPEN_THRESHOLD = 150;
export function installViewportSizing(): void {
const vv = window.visualViewport;
if (!vv) return;
const root = document.documentElement;
let raf = 0;
let baseline = vv.height;
const isEditing = () => {
const a = document.activeElement as HTMLElement | null;
if (!a) return false;
return a.tagName === "TEXTAREA" || a.tagName === "INPUT" || a.isContentEditable;
};
const sync = () => {
raf = 0;
root.style.setProperty("--app-vh", `${Math.round(vv.height)}px`);
root.style.setProperty("--app-top", `${Math.round(vv.offsetTop)}px`);
// Nothing focused ⇒ keyboard can't be open ⇒ this height is the baseline.
const editing = isEditing();
if (!editing) baseline = vv.height;
const kbOpen = editing && baseline - vv.height > KB_OPEN_THRESHOLD;
root.classList.toggle("kb-open", kbOpen);
};
const schedule = () => {
if (raf) return;