Added phone and responsive support on the tabnavigation added callapsables fixed colorscheme and setting background color

This commit is contained in:
Clément Le Bihan
2023-09-19 02:15:27 +02:00
parent c0c2918e72
commit dcca1b1f1c
4 changed files with 327 additions and 133 deletions

View File

@@ -1,137 +1,107 @@
import { View, Pressable, Text, Image } from 'react-native';
import { Divider, Text as NBText, Center } from 'native-base';
import TabNavigationButton from './TabNavigationButton';
import TabNavigationList from './TabNavigationList';
import { useAssets } from 'expo-asset';
import { useBreakpointValue } from 'native-base';
import { View } from 'react-native';
import TabNavigationDesktop from './TabNavigationDesktop';
import TabNavigationPhone from './TabNavigationPhone';
import { Ionicons } from '@expo/vector-icons';
import React, { useState } from 'react';
import { useSelector } from 'react-redux';
import { RootState } from '../../state/Store';
import useColorScheme from '../../hooks/colorScheme';
const TabNavigation = () => {
const colorScheme = useColorScheme();
const [icon] = useAssets(
colorScheme == 'light'
? require('../../assets/icon_light.png')
: require('../../assets/icon_dark.png')
);
const buttons = [
{
icon: 'icon',
label: 'label',
onPress: () => {},
onLongPress: () => {},
isActive: true,
},
{
icon: 'icon',
label: 'salut',
onPress: () => {},
onLongPress: () => {},
isActive: false,
},
];
export type NaviTab = {
id: string;
label: string;
icon?: React.ReactNode;
onPress?: () => void;
onLongPress?: () => void;
isActive?: boolean;
isCollapsed?: boolean;
iconName?: string;
};
const tabs = [
{
id: 'home',
label: 'Discovery',
icon: <Ionicons name="search" size={24} color="black" />,
iconName: 'search',
},
{
id: 'profile',
label: 'Profile',
icon: <Ionicons name="person" size={24} color="black" />,
iconName: 'person',
},
{
id: 'music',
label: 'Music',
icon: <Ionicons name="musical-notes" size={24} color="black" />,
iconName: 'musical-notes',
},
{
id: 'search',
label: 'Search',
icon: <Ionicons name="search" size={24} color="black" />,
iconName: 'search',
},
{
id: 'notifications',
label: 'Notifications',
icon: <Ionicons name="notifications" size={24} color="black" />,
iconName: 'notifications',
},
{
id: 'settings',
label: 'Settings',
icon: <Ionicons name="settings" size={24} color="white" />,
iconName: 'settings',
},
] as NaviTab[];
const TabNavigation = () => {
const screenSize = useBreakpointValue({ base: 'small', md: 'big' });
const [isDesktopCollapsed, setIsDesktopCollapsed] = useState(false);
const [activeTab, setActiveTab] = useState(tabs[0]?.id ?? 'home');
const colorScheme = useColorScheme();
const appTabs = tabs.map((t) => {
return {
...t,
onPress: () => setActiveTab(t.id),
icon: (
<Ionicons
// eslint-disable-next-line @typescript-eslint/no-explicit-any
name={t.iconName as any}
size={24}
color={colorScheme === 'dark' ? 'white' : 'black'}
/>
),
};
});
const others = [
{
label: 'Recently played',
},
{
label: 'Short',
},
{ label: 'Twinkle Twinkle' },
];
return (
<View
style={{
display: 'flex',
flexDirection: 'row',
width: '100%',
height: '100%',
backgroundColor: 'rgb(26, 36, 74)',
}}
>
<View>
<Center>
<View
style={{
display: 'flex',
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'flex-start',
flexShrink: 0,
padding: '10px',
}}
>
<Image
source={{ uri: icon?.at(0)?.uri }}
style={{
aspectRatio: 1,
width: '40px',
height: 'auto',
marginRight: '10px',
}}
/>
<NBText fontSize={'2xl'} selectable={false}>
Chromacase
</NBText>
</View>
</Center>
<View
style={{
display: 'flex',
width: '300px',
height: 'auto',
padding: '32px',
flexDirection: 'column',
justifyContent: 'space-between',
alignItems: 'flex-start',
flexGrow: 1,
}}
>
<TabNavigationList
style={{
flexShrink: 0,
gap: '20px',
}}
>
{buttons.map((button, index) => (
<TabNavigationButton
key={'tab-navigation-button-' + index}
{...button}
/>
))}
</TabNavigationList>
<TabNavigationList>
<Divider />
<TabNavigationList>
{others.map((other, index) => (
<View
key={'tab-navigation-other-' + index}
style={{
paddingHorizontal: '16px',
paddingVertical: '10px',
}}
>
<Text>{other.label}</Text>
</View>
))}
</TabNavigationList>
<Divider />
<TabNavigationList
style={{
gap: '20px',
}}
>
{[{ label: 'Settings' }, { label: 'Logout' }].map((button, index) => (
<TabNavigationButton
key={'tab-navigation-setting-button-' + index}
{...button}
/>
))}
</TabNavigationList>
</TabNavigationList>
</View>
</View>
<View>
<Text>Main content page</Text>
</View>
{screenSize === 'small' ? (
<TabNavigationPhone
tabs={appTabs}
activeTabID={activeTab}
setActiveTabID={setActiveTab}
/>
) : (
<TabNavigationDesktop
tabs={appTabs}
activeTabID={activeTab}
setActiveTabID={setActiveTab}
isCollapsed={isDesktopCollapsed}
setIsCollapsed={setIsDesktopCollapsed}
/>
)}
</View>
);
};

View File

@@ -1,12 +1,14 @@
import { View, Text } from 'react-native';
import { Pressable } from 'native-base';
import { View } from 'react-native';
import { Pressable, Text } from 'native-base';
import React from 'react';
type TabNavigationButtonProps = {
icon?: string;
icon?: React.ReactNode;
label: string;
onPress: () => void;
onLongPress: () => void;
isActive: boolean;
isCollapsed: boolean;
};
const TabNavigationButton = (props: TabNavigationButtonProps) => {
@@ -29,13 +31,23 @@ const TabNavigationButton = (props: TabNavigationButtonProps) => {
padding: '10px',
borderRadius: '8px',
flexGrow: 0,
boxShadow: (() => {
if (isHovered) {
return '0px 0px 16px 0px rgba(0, 0, 0, 0.25)';
} else if (props.isActive) {
return '0px 0px 8px 0px rgba(0, 0, 0, 0.25)';
} else {
return undefined;
}
})(),
backdropFilter: 'blur(2px)',
backgroundColor: (() => {
if (isPressed) {
return 'rgba(0, 0, 0, 0.1)';
} else if (isHovered) {
return 'rgba(0, 0, 0, 0.05)';
return 'rgba(231, 231, 232, 0.2)';
} else if (props.isActive) {
return 'rgba(0, 0, 0, 0.1)';
return 'rgba(16, 16, 20, 0.5)';
} else {
return 'transparent';
}
@@ -45,17 +57,17 @@ const TabNavigationButton = (props: TabNavigationButtonProps) => {
{props.icon && (
<View
style={{
marginRight: '10px',
marginRight: props.isCollapsed ? undefined : '10px',
}}
>
<Text>{props.icon}</Text>
{props.icon}
</View>
)}
<View>
{!props.isCollapsed && (
<Text numberOfLines={1} selectable={false}>
{props.label}
</Text>
</View>
)}
</View>
)}
</Pressable>
@@ -67,6 +79,7 @@ TabNavigationButton.defaultProps = {
onPress: () => {},
onLongPress: () => {},
isActive: false,
isCollapsed: false,
};
export default TabNavigationButton;

View File

@@ -0,0 +1,147 @@
import { View, Image } from 'react-native';
import { Divider, Text, Center } from 'native-base';
import TabNavigationButton from './TabNavigationButton';
import TabNavigationList from './TabNavigationList';
import { useAssets } from 'expo-asset';
import useColorScheme from '../../hooks/colorScheme';
import { NaviTab } from './TabNavigation';
type TabNavigationDesktopProps = {
tabs: NaviTab[];
isCollapsed: boolean;
setIsCollapsed: (isCollapsed: boolean) => void;
activeTabID: string;
setActiveTabID: (id: string) => void;
};
const TabNavigationDesktop = (props: TabNavigationDesktopProps) => {
const colorScheme = useColorScheme();
const [icon] = useAssets(
colorScheme == 'light'
? require('../../assets/icon_light.png')
: require('../../assets/icon_dark.png')
);
// settings is displayed separately (with logout)
const buttons = props.tabs.filter((tab) => tab.id !== 'settings');
const others = [
{
label: 'Recently played',
},
{
label: 'Short',
},
{ label: 'Twinkle Twinkle' },
];
return (
<View
style={{
display: 'flex',
flexDirection: 'row',
width: '100%',
height: '100%',
}}
>
<View>
<Center>
<View
style={{
display: 'flex',
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'flex-start',
flexShrink: 0,
padding: '10px',
}}
>
<Image
source={{ uri: icon?.at(0)?.uri }}
style={{
aspectRatio: 1,
width: '40px',
height: 'auto',
marginRight: '10px',
}}
/>
<Text fontSize={'2xl'} selectable={false}>
Chromacase
</Text>
</View>
</Center>
<View
style={{
display: 'flex',
width: '300px',
height: 'auto',
padding: '32px',
flexDirection: 'column',
justifyContent: 'space-between',
alignItems: 'flex-start',
flexGrow: 1,
}}
>
<TabNavigationList
style={{
flexShrink: 0,
gap: '20px',
}}
>
{buttons.map((button, index) => (
<TabNavigationButton
key={'tab-navigation-button-' + index}
icon={button.icon}
label={button.label}
isActive={button.id == props.activeTabID}
onPress={button.onPress}
onLongPress={button.onLongPress}
isCollapsed={props.isCollapsed}
/>
))}
</TabNavigationList>
<TabNavigationList>
<Divider />
<TabNavigationList>
{others.map((other, index) => (
<View
key={'tab-navigation-other-' + index}
style={{
paddingHorizontal: '16px',
paddingVertical: '10px',
}}
>
<Text>{other.label}</Text>
</View>
))}
</TabNavigationList>
<Divider />
<TabNavigationList
style={{
gap: '20px',
}}
>
{([props.tabs.find((t) => t.id === 'settings')] as NaviTab[]).map(
(button, index) => (
<TabNavigationButton
key={'tab-navigation-setting-button-' + index}
icon={button.icon}
label={button.label}
isActive={button.id == props.activeTabID}
onPress={button.onPress}
onLongPress={button.onLongPress}
isCollapsed={props.isCollapsed}
/>
)
)}
</TabNavigationList>
</TabNavigationList>
</View>
</View>
<View>
<Text>Main content page</Text>
</View>
</View>
);
};
export default TabNavigationDesktop;

View File

@@ -0,0 +1,64 @@
import { View } from 'react-native';
import { Text, Center } from 'native-base';
import TabNavigationButton from './TabNavigationButton';
import { NaviTab } from './TabNavigation';
type TabNavigationPhoneProps = {
tabs: NaviTab[];
activeTabID: string;
setActiveTabID: (id: string) => void;
};
const TabNavigationPhone = (props: TabNavigationPhoneProps) => {
return (
<View
style={{
width: '100%',
height: '100%',
display: 'flex',
flexDirection: 'column-reverse',
}}
>
<View
style={{
padding: '16px',
height: '90px',
width: '100%',
}}
>
<Center>
<View
style={{
display: 'flex',
padding: '8px',
justifyContent: 'space-evenly',
flexDirection: 'row',
alignItems: 'center',
alignSelf: 'stretch',
borderRadius: '8px',
backgroundColor: 'rgba(16, 16, 20, 0.5)',
}}
>
{props.tabs.map((tab) => (
<View key={'navigation-button-phone-' + tab.label}>
<TabNavigationButton
icon={tab.icon}
label={tab.label}
onPress={tab.onPress}
onLongPress={tab.onLongPress}
isActive={tab.id === props.activeTabID}
isCollapsed={tab.id != props.activeTabID}
/>
</View>
))}
</View>
</Center>
</View>
<View>
<Text>Main content page</Text>
</View>
</View>
);
};
export default TabNavigationPhone;