Files
iNaturalistReactNative/src/components/SharedComponents/FloatingActionBar.js
Chris 5b35e83b5c Utilize floating action bar and sticky toolbar in group photos ui (#527)
* lint

* Fix shadow on fab android

* lint
2023-03-14 12:42:53 -07:00

114 lines
2.7 KiB
JavaScript

// @flow
import classNames from "classnames";
import { View } from "components/styledComponents";
import * as React from "react";
import { useEffect, useMemo, useState } from "react";
import { Animated, Keyboard } from "react-native";
import { useTheme } from "react-native-paper";
import { getShadowStyle } from "styles/global";
const getShadow = shadowColor => getShadowStyle( {
shadowColor,
offsetWidth: 0,
offsetHeight: 4,
shadowOpacity: 0.4,
shadowRadius: 4,
elevation: 5
} );
type Props = {
position: "topStart" | "topEnd" | "bottomStart" | "bottomEnd",
containerClass?: string,
endY?: number | null,
children: React.Node,
show: boolean,
};
// Ensure this component is placed outside of scroll views
const FloatingActionBar = ( {
position = "bottomEnd",
endY = null,
containerClass,
children,
show
}: Props ): React.Node => {
const theme = useTheme();
const [keyboardHeight, setKeyboardHeight] = useState( 0 );
const [keyboardOpen, setKeyboardOpen] = useState( false );
const isBottom = position === "bottomEnd" || position === "bottomStart";
const start = isBottom ? 100 : -100;
const animate = useMemo(
() => new Animated.Value( show ? start : 0 ),
[start, show]
);
useEffect( () => {
const showSubscription = Keyboard.addListener(
"keyboardDidShow",
event => {
setKeyboardHeight( event.endCoordinates.height );
setKeyboardOpen( true );
}
);
const hideSubscription = Keyboard.addListener( "keyboardDidHide", () => {
setKeyboardOpen( false );
} );
return () => {
showSubscription.remove();
hideSubscription.remove();
};
}, [] );
useEffect( () => {
const sharedParams = {
velocity: 1,
tension: 2,
friction: 8,
useNativeDriver: true
};
const toValue = show ? 0 : start;
Animated.spring( animate, {
...sharedParams,
toValue
} ).start();
}, [keyboardOpen, keyboardHeight, position, show, animate, start] );
const effectiveKeyboardHeight = keyboardOpen ? keyboardHeight : 0;
const positionStyle = {};
if ( position.includes( "bottom" ) ) {
positionStyle.bottom = ( endY ?? 0 ) + effectiveKeyboardHeight;
}
if ( position.includes( "End" ) ) {
positionStyle.right = 0;
}
return (
<Animated.View
/* eslint-disable-next-line react-native/no-inline-styles */
style={{
overflow: "visible",
position: "absolute",
zIndex: 50,
transform: [{ translateY: animate }],
...positionStyle
}}
>
<View
className={classNames( "bg-white", containerClass )}
style={getShadow( theme.colors.primary )}
>
{children}
</View>
</Animated.View>
);
};
export default FloatingActionBar;