Added phone and responsive support on the tabnavigation added callapsables fixed colorscheme and setting background color
This commit is contained in:
@@ -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>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
|
||||
147
front/components/V2/TabNavigationDesktop.tsx
Normal file
147
front/components/V2/TabNavigationDesktop.tsx
Normal 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;
|
||||
64
front/components/V2/TabNavigationPhone.tsx
Normal file
64
front/components/V2/TabNavigationPhone.tsx
Normal 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;
|
||||
Reference in New Issue
Block a user