Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/respect-user-tab-bar-hidden.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'react-native-bottom-tabs': patch
---

Respect user-supplied `tabBarHidden` on `TabView`.
17 changes: 16 additions & 1 deletion apps/example/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ import NativeBottomTabsFreezeOnBlur from './Examples/NativeBottomTabsFreezeOnBlu
import NativeBottomTabsScreenLayout from './Examples/NativeBottomTabsScreenLayout';
import NativeBottomTabsLazy from './Examples/NativeBottomTabsLazy';
import BottomAccessoryView from './Examples/BottomAccessoryView';
import TabBarHidden from './Examples/TabBarHidden';
import CustomTabBar from './Examples/CustomTabBar';
import NativeBottomTabsTabBarHidden from './Examples/NativeBottomTabsTabBarHidden';
import { useLogger } from '@react-navigation/devtools';
import LazyTabs from './Examples/LazyTabs';
import { LogBox } from 'react-native';
Expand Down Expand Up @@ -103,6 +106,14 @@ const examples = [
screenOptions: { headerShown: false },
},
{ component: LazyTabs, name: 'Lazy Tabs' },
{
component: TabBarHidden,
name: 'Tab Bar Hidden',
},
{
component: CustomTabBar,
name: 'Custom tabBar',
},
{
component: FourTabsRippleColor,
name: 'Four Tabs with ripple Color',
Expand Down Expand Up @@ -157,7 +168,7 @@ const examples = [
},
{
component: NativeBottomTabsCustomTabBar,
name: 'Native Bottom Tabs with Custom Tab Bar',
name: 'Native Bottom Tabs with custom tabBar',
},
{
component: NativeBottomTabsScreenLayout,
Expand All @@ -167,6 +178,10 @@ const examples = [
component: NativeBottomTabsLazy,
name: 'Native Bottom Tabs with Lazy',
},
{
component: NativeBottomTabsTabBarHidden,
name: 'Native Bottom Tabs with tabBarHidden',
},
{ component: NativeBottomTabs, name: 'Native Bottom Tabs' },
{ component: JSBottomTabs, name: 'JS Bottom Tabs' },
{
Expand Down
104 changes: 104 additions & 0 deletions apps/example/src/Examples/CustomTabBar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import TabView from 'react-native-bottom-tabs';
import { useState } from 'react';
import { Pressable, StyleSheet, Text, View } from 'react-native';

const routes = [
{
key: 'article',
title: 'Article',
focusedIcon: require('../../assets/icons/article_dark.png'),
},
{
key: 'albums',
title: 'Albums',
focusedIcon: require('../../assets/icons/grid_dark.png'),
},
{
key: 'contacts',
title: 'Contacts',
focusedIcon: require('../../assets/icons/person_dark.png'),
},
];

export default function CustomTabBar() {
const [index, setIndex] = useState(0);

return (
<TabView
sidebarAdaptable
navigationState={{ index, routes }}
onIndexChange={setIndex}
renderScene={({ route }) => (
<View style={styles.screen}>
<Text style={styles.title}>{route.title}</Text>
</View>
)}
tabBar={() => (
<View style={styles.customTabBar}>
{routes.map((route, routeIndex) => {
const focused = routeIndex === index;

return (
<Pressable
key={route.key}
style={[
styles.customTabBarItem,
focused && styles.customTabBarItemFocused,
]}
onPress={() => setIndex(routeIndex)}
>
<Text
style={[
styles.customTabBarLabel,
focused && styles.customTabBarLabelFocused,
]}
>
{route.title}
</Text>
</Pressable>
);
})}
</View>
)}
/>
);
}

const styles = StyleSheet.create({
screen: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
padding: 24,
},
title: {
fontSize: 24,
fontWeight: '600',
},
customTabBar: {
flexDirection: 'row',
gap: 8,
paddingHorizontal: 12,
paddingTop: 10,
paddingBottom: 18,
backgroundColor: '#24292f',
},
customTabBarItem: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
minHeight: 44,
borderRadius: 6,
backgroundColor: '#3b434c',
},
customTabBarItemFocused: {
backgroundColor: '#ffffff',
},
customTabBarLabel: {
color: '#ffffff',
fontWeight: '600',
},
customTabBarLabelFocused: {
color: '#24292f',
},
});
93 changes: 93 additions & 0 deletions apps/example/src/Examples/NativeBottomTabsTabBarHidden.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import { createNativeBottomTabNavigator } from '@bottom-tabs/react-navigation';
import { useState } from 'react';
import { Button, StyleSheet, Text, View } from 'react-native';

const Tab = createNativeBottomTabNavigator();

type TabBarHiddenScreenProps = {
title: string;
tabBarHidden: boolean;
onToggleTabBarHidden: () => void;
};

function TabBarHiddenScreen({
title,
tabBarHidden,
onToggleTabBarHidden,
}: TabBarHiddenScreenProps) {
return (
<View style={styles.screen}>
<Text style={styles.title}>{title}</Text>
<Button
title={`${tabBarHidden ? 'Show' : 'Hide'} Tab Bar`}
onPress={onToggleTabBarHidden}
/>
</View>
);
}

export default function NativeBottomTabsTabBarHidden() {
const [tabBarHidden, setTabBarHidden] = useState(false);
const toggleTabBarHidden = () => setTabBarHidden((value) => !value);

return (
<Tab.Navigator sidebarAdaptable tabBarHidden={tabBarHidden}>
<Tab.Screen
name="Article"
options={{
tabBarIcon: () => require('../../assets/icons/article_dark.png'),
}}
>
{() => (
<TabBarHiddenScreen
title="Article"
tabBarHidden={tabBarHidden}
onToggleTabBarHidden={toggleTabBarHidden}
/>
)}
</Tab.Screen>
<Tab.Screen
name="Albums"
options={{
tabBarIcon: () => require('../../assets/icons/grid_dark.png'),
}}
>
{() => (
<TabBarHiddenScreen
title="Albums"
tabBarHidden={tabBarHidden}
onToggleTabBarHidden={toggleTabBarHidden}
/>
)}
</Tab.Screen>
<Tab.Screen
name="Contacts"
options={{
tabBarIcon: () => require('../../assets/icons/person_dark.png'),
}}
>
{() => (
<TabBarHiddenScreen
title="Contacts"
tabBarHidden={tabBarHidden}
onToggleTabBarHidden={toggleTabBarHidden}
/>
)}
</Tab.Screen>
</Tab.Navigator>
);
}

const styles = StyleSheet.create({
screen: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
gap: 16,
padding: 24,
},
title: {
fontSize: 24,
fontWeight: '600',
},
});
78 changes: 78 additions & 0 deletions apps/example/src/Examples/TabBarHidden.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import TabView from 'react-native-bottom-tabs';
import { useState } from 'react';
import { Button, StyleSheet, Text, View } from 'react-native';

const routes = [
{
key: 'article',
title: 'Article',
focusedIcon: require('../../assets/icons/article_dark.png'),
},
{
key: 'albums',
title: 'Albums',
focusedIcon: require('../../assets/icons/grid_dark.png'),
},
{
key: 'contacts',
title: 'Contacts',
focusedIcon: require('../../assets/icons/person_dark.png'),
},
];

type TabBarHiddenScreenProps = {
title: string;
tabBarHidden: boolean;
onToggleTabBarHidden: () => void;
};

function TabBarHiddenScreen({
title,
tabBarHidden,
onToggleTabBarHidden,
}: TabBarHiddenScreenProps) {
return (
<View style={styles.screen}>
<Text style={styles.title}>{title}</Text>
<Button
title={`${tabBarHidden ? 'Show' : 'Hide'} Tab Bar`}
onPress={onToggleTabBarHidden}
/>
</View>
);
}

export default function TabBarHidden() {
const [index, setIndex] = useState(0);
const [tabBarHidden, setTabBarHidden] = useState(false);

return (
<TabView
sidebarAdaptable
navigationState={{ index, routes }}
onIndexChange={setIndex}
renderScene={({ route }) => (
<TabBarHiddenScreen
title={route.title}
tabBarHidden={tabBarHidden}
onToggleTabBarHidden={() => setTabBarHidden((value) => !value)}
/>
)}
tabBarHidden={tabBarHidden}
/>
);
}

const styles = StyleSheet.create({
screen: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
gap: 16,
padding: 24,
},
title: {
fontSize: 24,
fontWeight: '600',
},
});
7 changes: 6 additions & 1 deletion packages/react-native-bottom-tabs/src/TabView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,10 @@
* @default 'locale'
*/
layoutDirection?: LayoutDirection;
/**
* Whether to hide the native tab bar.
*/
Comment thread
thiagobrez marked this conversation as resolved.
tabBarHidden?: boolean;
}

const ANDROID_MAX_TABS = 100;
Expand Down Expand Up @@ -255,6 +259,7 @@
labeled = Platform.OS !== 'android' ? true : undefined,
getFreezeOnBlur = ({ route }: { route: Route }) => route.freezeOnBlur,
tabBar: renderCustomTabBar,
tabBarHidden,
tabBarStyle,
tabLabelStyle,
renderBottomAccessoryView,
Expand Down Expand Up @@ -290,7 +295,7 @@

if (!loaded.includes(focusedKey)) {
// Set the current tab to be loaded if it was not loaded before
setLoaded((loaded) => [...loaded, focusedKey]);

Check warning on line 298 in packages/react-native-bottom-tabs/src/TabView.tsx

View workflow job for this annotation

GitHub Actions / lint

'loaded' is already declared in the upper scope on line 294 column 10
}

const icons = React.useMemo(
Expand Down Expand Up @@ -413,7 +418,7 @@
// When rendering a custom tab bar, icons can be React elements, which will not be properly resolved.
icons={renderCustomTabBar ? undefined : resolvedIconAssets}
selectedPage={focusedKey}
tabBarHidden={!!renderCustomTabBar}
tabBarHidden={tabBarHidden ?? !!renderCustomTabBar}
onTabLongPress={handleTabLongPress}
onPageSelected={handlePageSelected}
onTabBarMeasured={handleTabBarMeasured}
Expand Down
Loading