Skip to content

Commit

Permalink
feat: add ability to show tabs left or right
Browse files Browse the repository at this point in the history
  • Loading branch information
satya164 committed Sep 9, 2023
1 parent 17988a8 commit 93a4ec0
Show file tree
Hide file tree
Showing 9 changed files with 307 additions and 147 deletions.
225 changes: 136 additions & 89 deletions example/src/Screens/BottomTabs.tsx
Expand Up @@ -14,8 +14,14 @@ import {
import type { StackScreenProps } from '@react-navigation/stack';
import { BlurView } from 'expo-blur';
import * as React from 'react';
import { ScrollView, StatusBar, StyleSheet } from 'react-native';
import { Appbar } from 'react-native-paper';
import {
Image,
ScrollView,
StatusBar,
StyleSheet,
useWindowDimensions,
} from 'react-native';
import { Appbar, IconButton } from 'react-native-paper';

import { Albums } from '../Shared/Albums';
import { Chat } from '../Shared/Chat';
Expand Down Expand Up @@ -71,103 +77,144 @@ export function BottomTabs({
});
}, [navigation]);

const { showActionSheetWithOptions } = useActionSheet();

const dimensions = useWindowDimensions();

const [animation, setAnimation] =
React.useState<keyof typeof animations>('none');
const [isCompact, setIsCompact] = React.useState(false);

const { showActionSheetWithOptions } = useActionSheet();
const isLargeScreen = dimensions.width >= 1024;

return (
<Tab.Navigator
screenOptions={{
headerLeft: (props) => (
<HeaderBackButton {...props} onPress={navigation.goBack} />
),
headerRight: ({ tintColor }) => (
<Appbar.Action
icon={animation === 'none' ? 'heart-outline' : 'heart'}
color={tintColor}
onPress={() => {
const options = Object.keys(
animations
) as (keyof typeof animations)[];
<>
<Tab.Navigator
screenOptions={{
headerLeft: (props) => (
<HeaderBackButton {...props} onPress={navigation.goBack} />
),
headerRight: ({ tintColor }) => (
<Appbar.Action
icon={animation === 'none' ? 'heart-outline' : 'heart'}
color={tintColor}
onPress={() => {
const options = Object.keys(
animations
) as (keyof typeof animations)[];

showActionSheetWithOptions(
{
options: options.map((option) => {
if (option === animation) {
return `${option} (current)`;
}
showActionSheetWithOptions(
{
options: options.map((option) => {
if (option === animation) {
return `${option} (current)`;
}

return option;
}),
},
(index) => {
if (index != null) {
setAnimation(options[index]);
return option;
}),
},
(index) => {
if (index != null) {
setAnimation(options[index]);
}
}
}
);
}}
/>
),
...animations[animation],
}}
>
<Tab.Screen
name="TabStack"
component={SimpleStack}
options={{
title: 'Article',
tabBarIcon: getTabBarIcon('file-document'),
}}
/>
<Tab.Screen
name="TabChat"
component={Chat}
options={{
tabBarLabel: 'Chat',
tabBarIcon: getTabBarIcon('message-reply'),
tabBarBadge: 2,
}}
/>
<Tab.Screen
name="TabContacts"
component={Contacts}
options={{
title: 'Contacts',
tabBarIcon: getTabBarIcon('contacts'),
}}
/>
<Tab.Screen
name="TabAlbums"
component={AlbumsScreen}
options={{
title: 'Albums',
headerTintColor: '#fff',
headerTransparent: true,
headerBackground: () => (
<BlurView
tint="dark"
intensity={100}
style={StyleSheet.absoluteFill}
/>
),
tabBarIcon: getTabBarIcon('image-album'),
tabBarInactiveTintColor: 'rgba(255, 255, 255, 0.5)',
tabBarActiveTintColor: '#fff',
tabBarStyle: {
position: 'absolute',
borderTopColor: 'rgba(0, 0, 0, .2)',
},
tabBarBackground: () => (
<BlurView
tint="dark"
intensity={100}
style={StyleSheet.absoluteFill}
);
}}
/>
),
tabBarPosition: isLargeScreen ? 'left' : 'bottom',
tabBarLabelPosition:
isLargeScreen && isCompact ? 'below-icon' : undefined,
...animations[animation],
}}
/>
</Tab.Navigator>
>
<Tab.Screen
name="TabStack"
component={SimpleStack}
options={{
title: 'Article',
tabBarIcon: getTabBarIcon('file-document'),
}}
/>
<Tab.Screen
name="TabChat"
component={Chat}
options={{
tabBarLabel: 'Chat',
tabBarIcon: getTabBarIcon('message-reply'),
tabBarBadge: 2,
}}
/>
<Tab.Screen
name="TabContacts"
component={Contacts}
options={{
title: 'Contacts',
tabBarIcon: getTabBarIcon('contacts'),
}}
/>
<Tab.Screen
name="TabAlbums"
component={AlbumsScreen}
options={{
title: 'Albums',
headerTintColor: '#fff',
headerTransparent: true,
headerBackground: () => (
<BlurView
tint="dark"
intensity={100}
style={StyleSheet.absoluteFill}
/>
),
tabBarIcon: getTabBarIcon('image-album'),
tabBarInactiveTintColor: 'rgba(255, 255, 255, 0.5)',
tabBarActiveTintColor: '#fff',
tabBarStyle: {
position: isLargeScreen ? undefined : 'absolute',
borderColor: 'rgba(0, 0, 0, .2)',
},
tabBarBackground: () => (
<>
{isLargeScreen && (
<Image
source={require('../../assets/album-art-03.jpg')}
style={{
...StyleSheet.absoluteFillObject,
// Override default size of the image
height: undefined,
width: undefined,
resizeMode: 'cover',
}}
/>
)}
<BlurView
tint="dark"
intensity={100}
style={{
...StyleSheet.absoluteFillObject,
right: isLargeScreen
? // Offset for right border of the sidebar
-StyleSheet.hairlineWidth
: 0,
}}
/>
</>
),
}}
/>
</Tab.Navigator>
{isLargeScreen ? (
<IconButton
icon={isCompact ? 'chevron-double-right' : 'chevron-double-left'}
onPress={() => setIsCompact(!isCompact)}
style={{
position: 'absolute',
bottom: 0,
left: 0,
}}
/>
) : null}
</>
);
}
5 changes: 5 additions & 0 deletions packages/bottom-tabs/src/types.tsx
Expand Up @@ -223,6 +223,11 @@ export type BottomTabNavigationOptions = HeaderOptions & {
*/
tabBarBackground?: () => React.ReactNode;

/**
* Position of the tab bar on the screen. Defaults to `bottom`.
*/
tabBarPosition?: 'bottom' | 'left' | 'right';

/**
* Whether this screens should render the first time it's accessed. Defaults to `true`.
* Set it to `false` if you want to render the screen on initial render.
Expand Down

0 comments on commit 93a4ec0

Please sign in to comment.