From 7b08c7455d2fc260a98655f731bc24001b30ed19 Mon Sep 17 00:00:00 2001 From: Mo Gorhom Date: Tue, 31 Mar 2020 22:38:00 +0200 Subject: [PATCH 1/3] feat: add support to react-navigation 4 --- src/AnimatedTabBar.tsx | 73 ++++++++++++++++++++++++++++++++---------- 1 file changed, 56 insertions(+), 17 deletions(-) diff --git a/src/AnimatedTabBar.tsx b/src/AnimatedTabBar.tsx index a4d6db9..898c3ad 100644 --- a/src/AnimatedTabBar.tsx +++ b/src/AnimatedTabBar.tsx @@ -1,9 +1,9 @@ -import React, { useCallback, useMemo, useEffect } from 'react'; +import React, { useMemo, useEffect } from 'react'; import { View } from 'react-native'; import Animated, { useCode, onChange, call } from 'react-native-reanimated'; import { useValues } from 'react-native-redash'; import { useSafeArea } from 'react-native-safe-area-context'; -import { CommonActions } from '@react-navigation/native'; +import { CommonActions, Route } from '@react-navigation/native'; import { BottomTabBarProps } from '@react-navigation/bottom-tabs'; import { AnimatedTabBarItem } from './item'; import { TabsConfigsType, AnimationConfigProps } from './types'; @@ -24,10 +24,28 @@ interface AnimatedTabBarProps extends BottomTabBarProps, AnimationConfigProps { export const AnimatedTabBar = (props: AnimatedTabBarProps) => { // props - const { state, navigation, descriptors, tabs, duration, easing } = props; - const { routes } = state; + const { navigation, tabs, duration, easing } = props; // variables + const isReactNavigation5 = props.state ? true : false; + // @ts-ignore + const { + routes, + index: navigationIndex, + key: navigationKey, + }: { routes: Route[]; index: number; key: string } = useMemo(() => { + if (isReactNavigation5) { + return props.state; + } else { + return { + // @ts-ignore + index: props.navigation.state.index, + // @ts-ignore + routes: props.navigation.state.routes, + ket: '', + }; + } + }, [props, isReactNavigation5]); const safeArea = useSafeArea(); const [selectedIndex] = useValues([0], []); @@ -43,9 +61,28 @@ export const AnimatedTabBar = (props: AnimatedTabBarProps) => { ); // callbacks - const handleSelectedIndexChange = useCallback( - index => { - const { key, name } = state.routes[index]; + const getRouteLabel = (route: Route) => { + if (isReactNavigation5) { + const { descriptors } = props; + const { options } = descriptors[route.key]; + return options.title !== undefined ? options.title : route.name; + } else { + return route.key; + } + }; + + const getRouteTabConfigs = (route: Route) => { + console.log(route); + if (isReactNavigation5) { + return tabs[route.name]; + } else { + return tabs[route.key]; + } + }; + + const handleSelectedIndexChange = (index: number) => { + if (isReactNavigation5) { + const { key, name } = routes[index]; const event = navigation.emit({ type: 'tabPress', target: key, @@ -55,18 +92,21 @@ export const AnimatedTabBar = (props: AnimatedTabBarProps) => { if (!event.defaultPrevented) { navigation.dispatch({ ...CommonActions.navigate(name), - target: state.key, + target: navigationKey, }); } - }, - [state, navigation] - ); + } else { + // @ts-ignore + const { onTabPress } = props; + onTabPress({ route: routes[index] }); + } + }; // effects useEffect(() => { // @ts-ignore - selectedIndex.setValue(state.index); - }, [state, selectedIndex]); + selectedIndex.setValue(navigationIndex); + }, [navigationIndex, selectedIndex]); useCode( () => @@ -83,9 +123,8 @@ export const AnimatedTabBar = (props: AnimatedTabBarProps) => { return ( {routes.map((route, index) => { - const { options } = descriptors[route.key]; - const tabConfigs = tabs[route.name]; - const label = options.title !== undefined ? options.title : route.name; + const configs = getRouteTabConfigs(route); + const label = getRouteLabel(route); return ( { label={label} duration={duration} easing={easing} - {...tabConfigs} + {...configs} /> ); })} From 778e19ba76cbed110cde132503b0b38b5f04cfcf Mon Sep 17 00:00:00 2001 From: Mo Gorhom Date: Tue, 31 Mar 2020 22:54:38 +0200 Subject: [PATCH 2/3] docs: added react navigation 4 usage --- README.md | 174 +++++++++++++++++++++++++++++++++++---------------- package.json | 3 - 2 files changed, 120 insertions(+), 57 deletions(-) diff --git a/README.md b/README.md index 8127c80..8c2efb6 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ -# Animated TabBar [![npm](https://img.shields.io/npm/v/@gorhom/animated-tabbar)](https://www.npmjs.com/package/@gorhom/animated-tabbar) +# Animated TabBar [![npm](https://badgen.net/npm/v/@gorhom/animated-tabbar)](https://www.npmjs.com/package/@gorhom/animated-tabbar) -a 60fps animated tab bar to be used with `React Navigation` created with `Reanimated` 😎, inspired by [Aurélien Salomon](https://dribbble.com/aureliensalomon) works on [Dribbble](https://dribbble.com/shots/5925052-Google-Bottom-Bar-Navigation-Pattern-Mobile-UX-Design). +a 60fps animated tab bar to be used with `React Navigation v4 & v5` created with `Reanimated` 😎, inspired by [Aurélien Salomon](https://dribbble.com/aureliensalomon) works on [Dribbble](https://dribbble.com/shots/5925052-Google-Bottom-Bar-Navigation-Pattern-Mobile-UX-Design).

@@ -18,66 +18,132 @@ npm install @gorhom/animated-tabbar ## Usage -```tsx -import React from 'react'; -import { NavigationContainer } from '@react-navigation/native'; -import { createBottomTabNavigator } from '@react-navigation/bottom-tabs'; -import AnimatedTabBar, {TabsConfigsType} from '@gorhom/animated-tabbar'; - -const tabs: TabsConfigsType = { - Home: { - labelStyle: { - color: '#5B37B7', +

+ React Navigation v5 + + ```tsx + import React from 'react'; + import { NavigationContainer } from '@react-navigation/native'; + import { createBottomTabNavigator } from '@react-navigation/bottom-tabs'; + import AnimatedTabBar, {TabsConfigsType} from '@gorhom/animated-tabbar'; + + const tabs: TabsConfigsType = { + Home: { + labelStyle: { + color: '#5B37B7', + }, + icon: { + component: /* ICON COMPONENT */, + activeColor: 'rgba(91,55,183,1)', + inactiveColor: 'rgba(0,0,0,1)', + }, + background: { + activeColor: 'rgba(223,215,243,1)', + inactiveColor: 'rgba(223,215,243,0)', + }, }, - icon: { - component: /* ICON COMPONENT */, - activeColor: 'rgba(91,55,183,1)', - inactiveColor: 'rgba(0,0,0,1)', + Profile: { + labelStyle: { + color: '#1194AA', + }, + icon: { + component: /* ICON COMPONENT */, + activeColor: 'rgba(17,148,170,1)', + inactiveColor: 'rgba(0,0,0,1)', + }, + background: { + activeColor: 'rgba(207,235,239,1)', + inactiveColor: 'rgba(207,235,239,0)', + }, }, - background: { - activeColor: 'rgba(223,215,243,1)', - inactiveColor: 'rgba(223,215,243,0)', + }; + + const Tab = createBottomTabNavigator(); + + export default function App() { + return ( + + ( + + )} + > + + + + + ) + } + ``` +
+ +
+ React Navigation v4 + + ```tsx + import React from 'react'; + import {createAppContainer} from 'react-navigation'; + import {createBottomTabNavigator} from 'react-navigation-tabs'; + import {createStackNavigator} from 'react-navigation-stack'; + import {SafeAreaProvider} from 'react-native-safe-area-context'; + import AnimatedTabBar, {TabsConfigsType} from '@gorhom/animated-tabbar'; + + const tabs: TabsConfigsType = { + Home: { + labelStyle: { + color: '#5B37B7', + }, + icon: { + component: /* ICON COMPONENT */, + activeColor: 'rgba(91,55,183,1)', + inactiveColor: 'rgba(0,0,0,1)', + }, + background: { + activeColor: 'rgba(223,215,243,1)', + inactiveColor: 'rgba(223,215,243,0)', + }, }, - }, - Profile: { - labelStyle: { - color: '#1194AA', + Profile: { + labelStyle: { + color: '#1194AA', + }, + icon: { + component: /* ICON COMPONENT */, + activeColor: 'rgba(17,148,170,1)', + inactiveColor: 'rgba(0,0,0,1)', + }, + background: { + activeColor: 'rgba(207,235,239,1)', + inactiveColor: 'rgba(207,235,239,0)', + }, }, - icon: { - component: /* ICON COMPONENT */, - activeColor: 'rgba(17,148,170,1)', - inactiveColor: 'rgba(0,0,0,1)', + }; + + const TabNavigator = createBottomTabNavigator( + { + Home: HomeScreen, + Profile: ProfileScreen, }, - background: { - activeColor: 'rgba(207,235,239,1)', - inactiveColor: 'rgba(207,235,239,0)', + { + tabBarComponent: props => , }, - }, -}; + ); -const Tab = createBottomTabNavigator(); + const AppContainer = createAppContainer(TabNavigator); -export default function App() { - return ( - - ( - - )} - > - - - - - ) -} -``` + export default () => ( + + + + ); + ``` +
### Animated Icon diff --git a/package.json b/package.json index d09b327..759486b 100644 --- a/package.json +++ b/package.json @@ -66,9 +66,6 @@ "typescript": "^3.8.3" }, "peerDependencies": { - "@react-navigation/bottom-tabs": ">=5.0.0", - "@react-navigation/native": ">=5.0.0", - "@react-navigation/stack": ">=5.0.0", "react": "*", "react-native": "*", "react-native-gesture-handler": ">=1.6.0", From 6c46a70e5003df374bad9cdeb5b3c9cfdd7a80b3 Mon Sep 17 00:00:00 2001 From: Mo Gorhom Date: Tue, 31 Mar 2020 23:04:52 +0200 Subject: [PATCH 3/3] chore: remove debug console --- src/AnimatedTabBar.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/AnimatedTabBar.tsx b/src/AnimatedTabBar.tsx index 898c3ad..9aa5ebc 100644 --- a/src/AnimatedTabBar.tsx +++ b/src/AnimatedTabBar.tsx @@ -72,7 +72,6 @@ export const AnimatedTabBar = (props: AnimatedTabBarProps) => { }; const getRouteTabConfigs = (route: Route) => { - console.log(route); if (isReactNavigation5) { return tabs[route.name]; } else {