From 1f07c35f2889112b61e72238d7badea20f8f66c1 Mon Sep 17 00:00:00 2001 From: Daniel Williams Date: Mon, 11 May 2026 12:30:22 +0100 Subject: [PATCH 1/2] Fix lite story sheet keyboard spacing --- .../src/DrawerKeyboardInsetContext.tsx | 5 ++ .../src/MobileMenuDrawer.tsx | 77 +++++++------------ .../src/SearchResults.tsx | 6 +- packages/react-native-ui-lite/src/Tree.tsx | 6 +- 4 files changed, 42 insertions(+), 52 deletions(-) create mode 100644 packages/react-native-ui-lite/src/DrawerKeyboardInsetContext.tsx diff --git a/packages/react-native-ui-lite/src/DrawerKeyboardInsetContext.tsx b/packages/react-native-ui-lite/src/DrawerKeyboardInsetContext.tsx new file mode 100644 index 0000000000..03c8d899a0 --- /dev/null +++ b/packages/react-native-ui-lite/src/DrawerKeyboardInsetContext.tsx @@ -0,0 +1,5 @@ +import { createContext, useContext } from 'react'; + +export const DrawerKeyboardInsetContext = createContext(0); + +export const useDrawerKeyboardInset = () => useContext(DrawerKeyboardInsetContext); diff --git a/packages/react-native-ui-lite/src/MobileMenuDrawer.tsx b/packages/react-native-ui-lite/src/MobileMenuDrawer.tsx index 3d756a6456..ef0ef8e1c3 100644 --- a/packages/react-native-ui-lite/src/MobileMenuDrawer.tsx +++ b/packages/react-native-ui-lite/src/MobileMenuDrawer.tsx @@ -25,6 +25,7 @@ import { } from 'react-native'; import { useSelectedNode } from './SelectedNodeProvider'; +import { DrawerKeyboardInsetContext } from './DrawerKeyboardInsetContext'; import useAnimatedValue from './useAnimatedValue'; const flexStyle: ViewStyle = { flex: 1 }; @@ -52,68 +53,47 @@ export interface MobileMenuDrawerRef { export const useAnimatedModalHeight = () => { const { height } = useWindowDimensions(); const modalHeight = 0.65 * height; - const maxModalHeight = 0.85 * height; - const [sheetHeight, setSheetHeight] = useState(modalHeight); - const [keyboardInset, setKeyboardInset] = useState(0); - const [isKeyboardVisible, setIsKeyboardVisible] = useState(false); - - useEffect(() => { - setSheetHeight(modalHeight); - setKeyboardInset(0); - setIsKeyboardVisible(false); - }, [modalHeight]); + const maxKeyboardModalHeight = 0.75 * height; + const [keyboardHeight, setKeyboardHeight] = useState(0); + const isKeyboardVisible = keyboardHeight > 0; + const keyboardAvoidanceOffset = isKeyboardVisible + ? Math.min(keyboardHeight, maxKeyboardModalHeight - modalHeight) + : 0; + const sheetHeight = modalHeight + keyboardAvoidanceOffset; + const keyboardInset = isKeyboardVisible ? keyboardHeight : 0; useEffect(() => { const expand = (keyboardHeight: number = 0) => { - const maxKeyboardOffset = maxModalHeight - modalHeight; - const keyboardAvoidanceOffset = Math.min(keyboardHeight, maxKeyboardOffset); - - setIsKeyboardVisible(true); - setSheetHeight(modalHeight + keyboardAvoidanceOffset); - setKeyboardInset(Math.max(keyboardHeight - keyboardAvoidanceOffset, 0)); + setKeyboardHeight(keyboardHeight); }; const collapse = () => { - setSheetHeight(modalHeight); - setKeyboardInset(0); - setIsKeyboardVisible(false); - }; - - const handleKeyboardWillShow: KeyboardEventListener = (e) => { - if (Platform.OS === 'ios') { - expand(e.endCoordinates.height); - } - }; - - const handleKeyboardDidShow: KeyboardEventListener = (e) => { - if (Platform.OS === 'android') { - expand(e.endCoordinates.height); - } + setKeyboardHeight(0); }; - const handleKeyboardWillHide: KeyboardEventListener = (e) => { - if (Platform.OS === 'ios') { - collapse(); - } + const handleKeyboardShow: KeyboardEventListener = (e) => { + expand(e.endCoordinates.height); }; - const handleKeyboardDidHide: KeyboardEventListener = (e) => { - if (Platform.OS === 'android') { - collapse(); - } + const handleKeyboardHide: KeyboardEventListener = () => { + collapse(); }; const subscriptions = [ - Keyboard.addListener('keyboardWillShow', handleKeyboardWillShow), - Keyboard.addListener('keyboardDidShow', handleKeyboardDidShow), - Keyboard.addListener('keyboardWillHide', handleKeyboardWillHide), - Keyboard.addListener('keyboardDidHide', handleKeyboardDidHide), + Keyboard.addListener( + Platform.OS === 'ios' ? 'keyboardWillShow' : 'keyboardDidShow', + handleKeyboardShow + ), + Keyboard.addListener( + Platform.OS === 'ios' ? 'keyboardWillHide' : 'keyboardDidHide', + handleKeyboardHide + ), ]; return () => { subscriptions.forEach((subscription) => subscription.remove()); }; - }, [maxModalHeight, modalHeight]); + }, []); return { height: sheetHeight, @@ -271,9 +251,8 @@ export const MobileMenuDrawer = memo( () => ({ flex: 1, backgroundColor: theme.background.content, - paddingBottom: keyboardInset, }), - [keyboardInset, theme.background.content] + [theme.background.content] ); const scrollToSelectedButtonWrapperStyle = useMemo( @@ -320,8 +299,10 @@ export const MobileMenuDrawer = memo( - {children} - {showScrollToSelected ? ( + + {children} + + {showScrollToSelected && !isKeyboardVisible ? (