This repository has been archived on 2025-07-31. You can view files and clone it, but cannot push or open issues or pull requests.
Files
terminally-online/src/components/hideableBottomNavigationBar.tsx
2023-07-16 15:50:55 +03:00

102 lines
2.8 KiB
TypeScript

import React, { useEffect, useRef } from 'react';
import { BottomNavigation } from 'react-native-paper';
import { Animated, StyleSheet } from 'react-native';
import {
CommonActions,
NavigationHelpers,
ParamListBase,
TabNavigationState,
} from '@react-navigation/native';
import { EdgeInsets } from 'react-native-safe-area-context';
import { BottomTabNavigationEventMap } from '@react-navigation/bottom-tabs';
import { BottomTabDescriptorMap } from '@react-navigation/bottom-tabs/lib/typescript/src/types';
import { ROUTE } from '../types';
const hideableBottomNavigationBarStyles = StyleSheet.create({
bar: {
position: 'absolute',
bottom: 0,
left: 0,
right: 0,
},
});
const HideableBottomNavigationBar = ({
navigation,
state,
descriptors,
insets,
visible = true,
routeCallback,
}: {
navigation: NavigationHelpers<ParamListBase, BottomTabNavigationEventMap>;
state: TabNavigationState<ParamListBase>;
descriptors: BottomTabDescriptorMap;
insets: EdgeInsets;
visible?: boolean;
routeCallback?: (route: ROUTE) => void;
}) => {
const visibleAnim = useRef(new Animated.Value(visible ? 0 : 1)).current;
useEffect(() => {
Animated.timing(visibleAnim, {
toValue: visible ? 0 : 1,
duration: visible ? 200 : 150,
useNativeDriver: true,
}).start();
}, [visible, visibleAnim]);
return (
<Animated.View
style={{
marginBottom: insets.bottom,
transform: [
{
translateY: visibleAnim.interpolate({
inputRange: [0, 1],
outputRange: [0, 80],
}),
},
],
...hideableBottomNavigationBarStyles.bar,
}}>
<BottomNavigation.Bar
navigationState={state}
safeAreaInsets={insets}
onTabPress={({ route, preventDefault }) => {
const event = navigation.emit({
type: 'tabPress',
target: route.key,
canPreventDefault: true,
});
if (event.defaultPrevented) {
preventDefault();
} else {
navigation.dispatch({
...CommonActions.navigate(route.name, route.params),
target: state.key,
});
if (routeCallback) routeCallback(route.name as ROUTE);
}
}}
renderIcon={({ route, focused, color }) => {
const { options } = descriptors[route.key];
if (options.tabBarIcon) {
return options.tabBarIcon({
focused,
color,
size: 22,
});
}
}}
getLabelText={({ route }) => {
const { options } = descriptors[route.key];
return options.title ?? route.name;
}}
/>
</Animated.View>
);
};
export default HideableBottomNavigationBar;