1- import { useEffect } from 'react'
1+ import { useEffect , useRef } from 'react'
22import { useStore } from '@stores'
33
44const useVirtualKeyboard = ( ) => {
55 const { setKeyboardOpen, setKeyboardHeight, setVirtualKeyboardState } = useStore ( ( state ) => state )
6+ const previousIsOpenRef = useRef < boolean | null > ( null )
7+ const transitionTimeoutRef = useRef < NodeJS . Timeout | undefined > ( undefined )
68
79 useEffect ( ( ) => {
810 const visualViewport = window . visualViewport
911
1012 if ( ! visualViewport ) {
11- // Fallback for browsers without Visual Viewport API
1213 return
1314 }
1415
@@ -17,10 +18,38 @@ const useVirtualKeyboard = () => {
1718 const viewportHeight = visualViewport . height
1819 const keyboardHeight = windowHeight - viewportHeight
1920 const isKeyboardOpen = keyboardHeight > 0
21+ const previousIsOpen = previousIsOpenRef . current
2022
2123 setKeyboardOpen ( isKeyboardOpen )
2224 setKeyboardHeight ( keyboardHeight )
23- setVirtualKeyboardState ( isKeyboardOpen ? 'open' : 'closed' )
25+
26+ // Clear any existing transition timeout
27+ if ( transitionTimeoutRef . current ) {
28+ clearTimeout ( transitionTimeoutRef . current )
29+ }
30+
31+ // Determine state based on current vs previous
32+ if ( previousIsOpen === null ) {
33+ // Initial state - no transition
34+ setVirtualKeyboardState ( isKeyboardOpen ? 'open' : 'closed' )
35+ } else if ( previousIsOpen === false && isKeyboardOpen === true ) {
36+ // Keyboard is opening
37+ setVirtualKeyboardState ( 'opening' )
38+ transitionTimeoutRef . current = setTimeout ( ( ) => {
39+ setVirtualKeyboardState ( 'open' )
40+ } , 300 ) // Typical keyboard animation duration
41+ } else if ( previousIsOpen === true && isKeyboardOpen === false ) {
42+ // Keyboard is closing
43+ setVirtualKeyboardState ( 'closing' )
44+ transitionTimeoutRef . current = setTimeout ( ( ) => {
45+ setVirtualKeyboardState ( 'closed' )
46+ } , 300 )
47+ } else {
48+ // No state change - maintain current state
49+ setVirtualKeyboardState ( isKeyboardOpen ? 'open' : 'closed' )
50+ }
51+
52+ previousIsOpenRef . current = isKeyboardOpen
2453 }
2554
2655 // Initial check
@@ -33,6 +62,9 @@ const useVirtualKeyboard = () => {
3362 return ( ) => {
3463 visualViewport . removeEventListener ( 'resize' , handleViewportChange )
3564 visualViewport . removeEventListener ( 'scroll' , handleViewportChange )
65+ if ( transitionTimeoutRef . current ) {
66+ clearTimeout ( transitionTimeoutRef . current )
67+ }
3668 }
3769 } , [ ] )
3870}
0 commit comments