Fix iOS keyboard activation

- Remove setTimeout which breaks iOS gesture requirement for focus()
- Make textarea full-size overlay with near-zero opacity (iOS needs visible element)
- Remove pointer-events:none and negative z-index that prevented touch
- Use touchend instead of touchstart for more reliable iOS behavior
- Call focus() synchronously within user gesture handler
This commit is contained in:
GitHub Copilot
2026-01-28 07:42:25 +00:00
parent e05c1cd1b4
commit 67b12e5570
2 changed files with 34 additions and 23 deletions
File diff suppressed because one or more lines are too long
+22 -16
View File
@@ -383,17 +383,23 @@ class WebTerminal {
textarea.setAttribute("spellcheck", "false"); textarea.setAttribute("spellcheck", "false");
textarea.setAttribute("inputmode", "text"); textarea.setAttribute("inputmode", "text");
textarea.setAttribute("enterkeyhint", "send"); textarea.setAttribute("enterkeyhint", "send");
// Style to be invisible but still focusable (not display:none) // iOS requires the element to be "visible" and interactive for keyboard
// Use opacity near-zero but not zero, and keep it in the visible area
textarea.style.cssText = ` textarea.style.cssText = `
position: absolute; position: absolute;
left: 0; left: 0;
top: 0; top: 0;
width: 1px; width: 100%;
height: 1px; height: 100%;
opacity: 0; opacity: 0.01;
z-index: -1; z-index: 1;
pointer-events: none; color: transparent;
background: transparent;
border: none;
outline: none;
resize: none;
font-size: 16px; font-size: 16px;
caret-color: transparent;
`; `;
// Font size 16px prevents iOS auto-zoom on focus // Font size 16px prevents iOS auto-zoom on focus
@@ -447,24 +453,24 @@ class WebTerminal {
}); });
// Focus textarea on touch/click to show mobile keyboard // Focus textarea on touch/click to show mobile keyboard
this.element.addEventListener("touchstart", () => { // iOS requires focus() to be called synchronously within the gesture
this.focusMobileInput(); this.element.addEventListener("touchend", (e) => {
// Only respond to single touch on terminal area
if (e.target === textarea || e.target === this.element || this.element.contains(e.target as Node)) {
this.mobileInput?.focus();
}
}, { passive: true }); }, { passive: true });
this.element.addEventListener("click", () => { this.element.addEventListener("click", () => {
this.focusMobileInput(); this.mobileInput?.focus();
this.terminal.focus();
}); });
} }
/** Focus the mobile input to show keyboard */ /** Focus the mobile input to show keyboard */
private focusMobileInput(): void { private focusMobileInput(): void {
if (this.mobileInput) { // For programmatic focus (not from user gesture), this may not show keyboard on iOS
// Small delay helps with iOS keyboard activation this.mobileInput?.focus();
setTimeout(() => {
this.mobileInput?.focus({ preventScroll: true });
}, 10);
}
// Also focus the terminal for desktop
this.terminal.focus(); this.terminal.focus();
} }