From b7e6ee490cb5d2c6cf9fe81b530406fe60eec953 Mon Sep 17 00:00:00 2001 From: PEDZEO Date: Wed, 21 Jan 2026 02:21:57 +0300 Subject: [PATCH] Fix keyboard detection using focus events instead of visualViewport --- src/components/layout/Layout.tsx | 33 ++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/src/components/layout/Layout.tsx b/src/components/layout/Layout.tsx index b8b83c9..fbfdd1f 100644 --- a/src/components/layout/Layout.tsx +++ b/src/components/layout/Layout.tsx @@ -210,23 +210,32 @@ export default function Layout({ children }: LayoutProps) { } }, [mobileMenuOpen]) - // Detect virtual keyboard open/close using visualViewport API + // Detect virtual keyboard by tracking focus on input elements useEffect(() => { - const viewport = window.visualViewport - if (!viewport) return - - const handleResize = () => { - // Keyboard is considered open if viewport height is significantly smaller than window height - const heightDiff = window.innerHeight - viewport.height - setIsKeyboardOpen(heightDiff > 150) + const handleFocusIn = (e: FocusEvent) => { + const target = e.target as HTMLElement + if (target.tagName === 'INPUT' || target.tagName === 'TEXTAREA' || target.isContentEditable) { + setIsKeyboardOpen(true) + } } - viewport.addEventListener('resize', handleResize) - viewport.addEventListener('scroll', handleResize) + const handleFocusOut = (e: FocusEvent) => { + const relatedTarget = e.relatedTarget as HTMLElement | null + // Only close if not focusing another input + if (!relatedTarget || + (relatedTarget.tagName !== 'INPUT' && + relatedTarget.tagName !== 'TEXTAREA' && + !relatedTarget.isContentEditable)) { + setIsKeyboardOpen(false) + } + } + + document.addEventListener('focusin', handleFocusIn) + document.addEventListener('focusout', handleFocusOut) return () => { - viewport.removeEventListener('resize', handleResize) - viewport.removeEventListener('scroll', handleResize) + document.removeEventListener('focusin', handleFocusIn) + document.removeEventListener('focusout', handleFocusOut) } }, [])