Skip to content

Commit 7d3bd08

Browse files
feat: add react-navigation integration for BottomNavigation (callstack#3676)
Co-authored-by: Dimitar Nestorov <[email protected]>
1 parent 252b1a6 commit 7d3bd08

20 files changed

+1763
-825
lines changed

Diff for: docs/docusaurus.config.js

+1
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ const config = {
7474
Banner: 'Banner',
7575
BottomNavigation: {
7676
BottomNavigation: 'BottomNavigation/BottomNavigation',
77+
BottomNavigationBar: 'BottomNavigation/BottomNavigationBar',
7778
},
7879
Button: {
7980
Button: 'Button/Button',

Diff for: docs/static/screenshots/bottom-navigation-tabs.jpg

12.9 KB
Loading

Diff for: example/metro.config.js

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ const modules = [
1515
'@expo/vector-icons',
1616
'expo-constants',
1717
...Object.keys(pak.peerDependencies),
18+
'@react-navigation/native',
1819
];
1920

2021
module.exports = {

Diff for: example/src/ExampleList.tsx

+4
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import AppbarExample from './Examples/AppbarExample';
1111
import AvatarExample from './Examples/AvatarExample';
1212
import BadgeExample from './Examples/BadgeExample';
1313
import BannerExample from './Examples/BannerExample';
14+
import BottomNavigationBarExample from './Examples/BottomNavigationBarExample';
1415
import BottomNavigationExample from './Examples/BottomNavigationExample';
1516
import ButtonExample from './Examples/ButtonExample';
1617
import CardExample from './Examples/CardExample';
@@ -26,6 +27,7 @@ import ListAccordionExample from './Examples/ListAccordionExample';
2627
import ListAccordionExampleGroup from './Examples/ListAccordionGroupExample';
2728
import ListItemExample from './Examples/ListItemExample';
2829
import ListSectionExample from './Examples/ListSectionExample';
30+
import MaterialBottomTabNavigatorExample from './Examples/MaterialBottomTabNavigatorExample';
2931
import MenuExample from './Examples/MenuExample';
3032
import ProgressBarExample from './Examples/ProgressBarExample';
3133
import RadioButtonExample from './Examples/RadioButtonExample';
@@ -60,6 +62,7 @@ export const mainExamples: Record<
6062
avatar: AvatarExample,
6163
badge: BadgeExample,
6264
banner: BannerExample,
65+
bottomNavigationBarExample: BottomNavigationBarExample,
6366
bottomNavigation: BottomNavigationExample,
6467
button: ButtonExample,
6568
card: CardExample,
@@ -75,6 +78,7 @@ export const mainExamples: Record<
7578
listAccordionGroup: ListAccordionExampleGroup,
7679
listSection: ListSectionExample,
7780
listItem: ListItemExample,
81+
materialBottomTabNavigator: MaterialBottomTabNavigatorExample,
7882
menu: MenuExample,
7983
progressbar: ProgressBarExample,
8084
radio: RadioButtonExample,

Diff for: example/src/Examples/BottomNavigationBarExample.tsx

+90
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
import React from 'react';
2+
import { View, StyleSheet } from 'react-native';
3+
4+
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
5+
import { Text, BottomNavigation } from 'react-native-paper';
6+
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
7+
8+
const Tab = createBottomTabNavigator();
9+
10+
function HomeScreen() {
11+
return (
12+
<View style={styles.container}>
13+
<Text variant="headlineMedium">Home!</Text>
14+
</View>
15+
);
16+
}
17+
18+
function SettingsScreen() {
19+
return (
20+
<View style={styles.container}>
21+
<Text variant="headlineMedium">Settings!</Text>
22+
</View>
23+
);
24+
}
25+
26+
export default function BottomNavigationBarExample() {
27+
return (
28+
<Tab.Navigator
29+
screenOptions={{
30+
headerShown: false,
31+
}}
32+
tabBar={({ navigation, state, descriptors, insets }) => (
33+
<BottomNavigation.Bar
34+
navigationState={state}
35+
safeAreaInsets={insets}
36+
onTabPress={({ route, preventDefault }) => {
37+
const event = navigation.emit({
38+
type: 'tabPress',
39+
target: route.key,
40+
canPreventDefault: true,
41+
});
42+
43+
if (event.defaultPrevented) {
44+
preventDefault();
45+
} else {
46+
navigation.navigate(route);
47+
}
48+
}}
49+
renderIcon={({ route, focused, color }) =>
50+
descriptors[route.key].options.tabBarIcon?.({
51+
focused,
52+
color,
53+
size: 24,
54+
}) || null
55+
}
56+
getLabelText={({ route }) => descriptors[route.key].route.name}
57+
/>
58+
)}
59+
>
60+
<Tab.Screen
61+
name="Home"
62+
component={HomeScreen}
63+
options={{
64+
tabBarIcon: ({ color, size }) => {
65+
return <Icon name="home" size={size} color={color} />;
66+
},
67+
}}
68+
/>
69+
<Tab.Screen
70+
name="Settings"
71+
component={SettingsScreen}
72+
options={{
73+
tabBarIcon: ({ color, size }) => {
74+
return <Icon name="cog" size={size} color={color} />;
75+
},
76+
}}
77+
/>
78+
</Tab.Navigator>
79+
);
80+
}
81+
82+
BottomNavigationBarExample.title = 'Bottom Navigation Bar';
83+
84+
const styles = StyleSheet.create({
85+
container: {
86+
flex: 1,
87+
justifyContent: 'center',
88+
alignItems: 'center',
89+
},
90+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
import React from 'react';
2+
import { StyleSheet, Text, View } from 'react-native';
3+
4+
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
5+
6+
import { createMaterialBottomTabNavigator } from '../../../src/react-navigation';
7+
8+
const Tab = createMaterialBottomTabNavigator();
9+
10+
export default function MaterialBottomTabNavigatorExample() {
11+
return (
12+
<Tab.Navigator
13+
initialRouteName="Feed"
14+
activeColor="#e91e63"
15+
style={styles.tabs}
16+
>
17+
<Tab.Screen
18+
name="Feed"
19+
component={Feed}
20+
options={{
21+
tabBarLabel: 'Home',
22+
tabBarIcon: ({ color }) => (
23+
<Icon name="home" color={color} size={26} />
24+
),
25+
}}
26+
/>
27+
<Tab.Screen
28+
name="Notifications"
29+
component={Notifications}
30+
options={{
31+
tabBarLabel: 'Updates',
32+
tabBarIcon: ({ color }) => (
33+
<Icon name="bell" color={color} size={26} />
34+
),
35+
}}
36+
/>
37+
<Tab.Screen
38+
name="Profile"
39+
component={Profile}
40+
options={{
41+
tabBarLabel: 'Profile',
42+
tabBarIcon: ({ color }) => (
43+
<Icon name="account" color={color} size={26} />
44+
),
45+
}}
46+
/>
47+
</Tab.Navigator>
48+
);
49+
}
50+
51+
MaterialBottomTabNavigatorExample.title = 'Material Bottom Tab Navigator';
52+
53+
function Feed() {
54+
return (
55+
<View style={styles.screen}>
56+
<Text>Feed!</Text>
57+
</View>
58+
);
59+
}
60+
61+
function Profile() {
62+
return (
63+
<View style={styles.screen}>
64+
<Text>Profile!</Text>
65+
</View>
66+
);
67+
}
68+
69+
function Notifications() {
70+
return (
71+
<View style={styles.screen}>
72+
<Text>Notifications!</Text>
73+
</View>
74+
);
75+
}
76+
77+
const styles = StyleSheet.create({
78+
screen: {
79+
flex: 1,
80+
justifyContent: 'center',
81+
alignItems: 'center',
82+
},
83+
// eslint-disable-next-line react-native/no-color-literals
84+
tabs: {
85+
backgroundColor: 'tomato',
86+
},
87+
});

Diff for: example/src/Examples/ThemingWithReactNavigation.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ const HomeTab = () => {
3737
component={HomeScreen}
3838
options={{
3939
tabBarIcon: ({ color, size }) => {
40-
return <Icon name={'home'} size={size} color={color} />;
40+
return <Icon name="home" size={size} color={color} />;
4141
},
4242
}}
4343
/>
@@ -46,7 +46,7 @@ const HomeTab = () => {
4646
component={SettingsScreen}
4747
options={{
4848
tabBarIcon: ({ color, size }) => {
49-
return <Icon name={'cog'} size={size} color={color} />;
49+
return <Icon name="cog" size={size} color={color} />;
5050
},
5151
}}
5252
/>

Diff for: package.json

+2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
"files": [
1111
"src",
1212
"lib",
13+
"react-navigation",
1314
"babel.js"
1415
],
1516
"sideEffects": false,
@@ -57,6 +58,7 @@
5758
"@babel/runtime": "^7.20.7",
5859
"@callstack/eslint-config": "^13.0.2",
5960
"@commitlint/config-conventional": "^8.3.4",
61+
"@react-navigation/native": "^6.1.2",
6062
"@release-it/conventional-changelog": "^1.1.0",
6163
"@testing-library/jest-native": "^5.4.1",
6264
"@testing-library/react-native": "11.5.0",

Diff for: react-navigation/package.json

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"main": "../lib/commonjs/react-navigation/index",
3+
"module": "../lib/module/react-navigation/index",
4+
"react-native": "../src/react-navigation/index",
5+
"types": "../lib/typescript/react-navigation/index"
6+
}

0 commit comments

Comments
 (0)