fix: keyboard visibility offset issue - remove problematic top positioning

- Remove top/bottom positioning from modal-content when keyboard visible
- Reset --viewport-offset-top to 0 when keyboard closes
- Add focusout handler to help reset keyboard state on iOS
- Simplify modal keyboard CSS to only adjust max-height

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
arkon
2026-01-31 07:58:12 +01:00
co-authored by Claude Opus 4.5
parent fd30040289
commit 1288338e58
4 changed files with 38 additions and 19 deletions
+31 -1
View File
@@ -224,6 +224,9 @@ const KeyboardHandler = {
// Focus event handling for scrolling inputs into view
document.addEventListener('focusin', this.handleFocusIn.bind(this));
// Focusout handler to help reset state when leaving all inputs
document.addEventListener('focusout', this.handleFocusOut.bind(this));
},
/** Handle visualViewport resize - detect keyboard */
@@ -257,9 +260,14 @@ const KeyboardHandler = {
this.isKeyboardVisible = visible;
this.keyboardHeight = height;
// Update CSS custom property
// Update CSS custom properties
document.documentElement.style.setProperty('--keyboard-height', `${height}px`);
// Reset viewport offset when keyboard closes
if (!visible) {
document.documentElement.style.setProperty('--viewport-offset-top', '0px');
}
// Toggle class for CSS targeting
document.body.classList.toggle('keyboard-visible', visible);
@@ -280,6 +288,28 @@ const KeyboardHandler = {
}, 350);
},
/** Handle focus leaving input elements - help reset keyboard state */
handleFocusOut(e) {
if (!this.isInputElement(e.target)) return;
// Small delay to check if focus moved to another input
setTimeout(() => {
const activeEl = document.activeElement;
// If focus left all inputs, ensure keyboard state is reset
if (!this.isInputElement(activeEl)) {
// The visualViewport resize event should handle this,
// but we reset just in case on iOS where it can be flaky
if (this.isKeyboardVisible && window.visualViewport) {
const vv = window.visualViewport;
const heightDiff = this.initialViewportHeight - vv.height;
if (heightDiff < 100) {
this.updateKeyboardState(false, 0);
}
}
}
}, 300);
},
/** Check if element is an input that triggers keyboard */
isInputElement(el) {
if (!el) return false;
+1 -16
View File
@@ -8420,10 +8420,7 @@ kbd {
.keyboard-visible .modal-content {
/* Don't take full height - resize with keyboard */
height: auto;
max-height: calc(100dvh - var(--keyboard-height) - var(--safe-area-top));
/* Anchor to top */
top: var(--safe-area-top);
bottom: auto;
max-height: calc(100dvh - var(--keyboard-height));
}
.keyboard-visible .modal-body {
@@ -8432,18 +8429,6 @@ kbd {
overflow-y: auto;
-webkit-overflow-scrolling: touch;
}
/* Ensure modal footer stays visible above keyboard */
.keyboard-visible .modal-footer,
.keyboard-visible .wizard-footer,
.keyboard-visible .form-actions {
padding-bottom: 0.5rem;
}
/* Smooth transition for keyboard appearance */
.modal-content {
transition: max-height 0.2s ease-out, top 0.2s ease-out;
}
}
/* ============================================================================