diff --git a/frontend/src/components/MessageInput.css b/frontend/src/components/MessageInput.css index 94cfee5..be9786e 100644 --- a/frontend/src/components/MessageInput.css +++ b/frontend/src/components/MessageInput.css @@ -247,3 +247,9 @@ } } +/* iOS keyboard fix: when keyboard is open, env(safe-area-inset-bottom) stays at ~34px + instead of dropping to 0 — remove it so there's no empty gap below the input */ +.keyboard-open .message-input-area { + padding-bottom: 12px; +} + diff --git a/frontend/src/main.jsx b/frontend/src/main.jsx index 267355f..1055e17 100644 --- a/frontend/src/main.jsx +++ b/frontend/src/main.jsx @@ -95,6 +95,29 @@ if ('serviceWorker' in navigator) { }, { passive: true }); })(); +// ─── iOS virtual keyboard layout fix ──────────────────────────────────────── +// iOS Safari/PWA ignores `interactive-widget=resizes-content` and instead +// scrolls the page when the keyboard opens, causing two bugs: +// 1. The chat header scrolls off-screen ("NO MESSAGE TITLE") +// 2. env(safe-area-inset-bottom) stays at ~34px, adding extra padding below input +// +// Fix: track the Visual Viewport height and expose it as --visual-viewport-height +// so .chat-layout always fills exactly the visible area above the keyboard. +// Also toggle a `keyboard-open` class so CSS can remove the safe-area padding +// from the message input (the keyboard covers the home indicator area anyway). +if (window.visualViewport) { + const onViewportChange = () => { + const h = window.visualViewport.height; + document.documentElement.style.setProperty('--visual-viewport-height', `${h}px`); + // window.innerHeight doesn't shrink on iOS when keyboard opens — the gap IS the keyboard. + const keyboardVisible = (window.innerHeight - h) > 150; + document.documentElement.classList.toggle('keyboard-open', keyboardVisible); + }; + window.visualViewport.addEventListener('resize', onViewportChange); + window.visualViewport.addEventListener('scroll', onViewportChange); + onViewportChange(); // set immediately so first render uses the correct height +} + // Clear badge count when user focuses the app window.addEventListener('focus', () => { if (navigator.clearAppBadge) navigator.clearAppBadge().catch(() => {}); diff --git a/frontend/src/pages/Chat.css b/frontend/src/pages/Chat.css index 4d401b3..9a56417 100644 --- a/frontend/src/pages/Chat.css +++ b/frontend/src/pages/Chat.css @@ -1,8 +1,8 @@ .chat-layout { display: flex; flex-direction: column; - height: 100vh; height: 100dvh; + height: var(--visual-viewport-height, 100dvh); /* iOS keyboard fix: shrinks to visible area above keyboard */ overflow: hidden; background: var(--background); }