Skip to content

Commit

Permalink
Animate bottom sheet's height with Reanimated
Browse files Browse the repository at this point in the history
Pass `currentHeight` in bottom sheet navigation context
  • Loading branch information
fluiddot committed Jul 12, 2023
1 parent 3f5a220 commit 634b2fd
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { createContext } from '@wordpress/element';
// Navigation context in BottomSheet is necessary for controlling the
// height of navigation container.
export const BottomSheetNavigationContext = createContext( {
currentHeight: 1,
currentHeight: { value: 0 },
setHeight: () => {},
} );

Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
/**
* External dependencies
*/
import { View, Easing } from 'react-native';
import { NavigationContainer, DefaultTheme } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import Animated, {
Easing,
useAnimatedStyle,
useSharedValue,
withTiming,
} from 'react-native-reanimated';

/**
* WordPress dependencies
*/
import {
useState,
useContext,
useMemo,
useCallback,
Expand All @@ -23,11 +27,11 @@ import { usePreferredColorSchemeStyle } from '@wordpress/compose';
/**
* Internal dependencies
*/
import { performLayoutAnimation } from '../../layout-animation';
import {
BottomSheetNavigationContext,
BottomSheetNavigationProvider,
} from './bottom-sheet-navigation-context';
import { BottomSheetContext } from '../bottom-sheet-context';

import styles from './styles.scss';

Expand Down Expand Up @@ -57,7 +61,8 @@ const options = {
cardStyleInterpolator: fadeConfig,
};

const ANIMATION_DURATION = 190;
const HEIGHT_ANIMATION_DURATION = 300;
const DEFAULT_HEIGHT = 1;

function BottomSheetNavigationContainer( {
children,
Expand All @@ -67,9 +72,11 @@ function BottomSheetNavigationContainer( {
style,
} ) {
const Stack = useRef( createStackNavigator() ).current;
const context = useContext( BottomSheetNavigationContext );
const [ currentHeight, setCurrentHeight ] = useState(
context.currentHeight || 1
const navigationContext = useContext( BottomSheetNavigationContext );
const { maxHeight: sheetMaxHeight, isMaxHeightSet: isSheetMaxHeightSet } =
useContext( BottomSheetContext );
const currentHeight = useSharedValue(
navigationContext.currentHeight?.value || DEFAULT_HEIGHT
);

const backgroundStyle = usePreferredColorSchemeStyle(
Expand All @@ -87,37 +94,35 @@ function BottomSheetNavigationContainer( {

const setHeight = useCallback(
( height ) => {
// The screen is fullHeight.
if (
typeof height === 'string' &&
typeof height !== typeof currentHeight
height > DEFAULT_HEIGHT &&
Math.round( height ) !== Math.round( currentHeight.value )
) {
performLayoutAnimation( ANIMATION_DURATION );
setCurrentHeight( height );

return;
}

if (
height > 1 &&
Math.round( height ) !== Math.round( currentHeight )
) {
if ( currentHeight === 1 ) {
setCurrentHeight( height );
} else if ( animate ) {
performLayoutAnimation( ANIMATION_DURATION );
setCurrentHeight( height );
// If max height is set in the bottom sheet, we clamp
// the new height using that value.
const newHeight = isSheetMaxHeightSet
? Math.min( sheetMaxHeight, height )
: height;
const shouldAnimate =
animate && currentHeight.value !== DEFAULT_HEIGHT;

if ( shouldAnimate ) {
currentHeight.value = withTiming( newHeight, {
duration: HEIGHT_ANIMATION_DURATION,
easing: Easing.out( Easing.cubic ),
} );
} else {
setCurrentHeight( height );
currentHeight.value = newHeight;
}
}
},
// Disable reason: deferring this refactor to the native team.
// see https://github.com/WordPress/gutenberg/pull/41166
// eslint-disable-next-line react-hooks/exhaustive-deps
[ currentHeight ]
[ animate, currentHeight, isSheetMaxHeightSet, sheetMaxHeight ]
);

const animatedStyles = useAnimatedStyle( () => ( {
height: currentHeight.value,
} ) );

const screens = useMemo( () => {
return Children.map( children, ( child ) => {
let screen = child;
Expand All @@ -143,12 +148,9 @@ function BottomSheetNavigationContainer( {

return useMemo( () => {
return (
<View style={ [ style, { height: currentHeight } ] }>
<Animated.View style={ [ style, animatedStyles ] }>
<BottomSheetNavigationProvider
value={ {
setHeight,
currentHeight,
} }
value={ { setHeight, currentHeight } }
>
{ main ? (
<NavigationContainer theme={ _theme }>
Expand All @@ -168,12 +170,12 @@ function BottomSheetNavigationContainer( {
</Stack.Navigator>
) }
</BottomSheetNavigationProvider>
</View>
</Animated.View>
);
// Disable reason: deferring this refactor to the native team.
// see https://github.com/WordPress/gutenberg/pull/41166
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ currentHeight, _theme ] );
}, [ _theme ] );
}

export default BottomSheetNavigationContainer;

0 comments on commit 634b2fd

Please sign in to comment.