redesign completed
alot of work ahead
This commit is contained in:
1 parent
73d2c4c1ed
commit
febcdc111e
18 files changed
+1591
-845
No files matched your search
@@ -0,0 +1,143 @@
|
||||
import React from 'react';
|
||||
import { View, StyleSheet, TouchableOpacity, Platform, Dimensions } from 'react-native';
|
||||
import { BottomTabBarProps } from '@react-navigation/bottom-tabs';
|
||||
import { Ionicons } from '@expo/vector-icons';
|
||||
import { LinearGradient } from 'expo-linear-gradient';
|
||||
import { theme } from '../styles/theme';
|
||||
import { Animated } from 'react-native';
|
||||
|
||||
const { width } = Dimensions.get('window');
|
||||
|
||||
export function CustomTabBar({ state, descriptors, navigation }: BottomTabBarProps) {
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<LinearGradient
|
||||
colors={['rgba(255, 255, 255, 0.9)', 'rgba(255, 255, 255, 0.7)']}
|
||||
style={[styles.tabBar, theme.shadows.medium]}
|
||||
start={{ x: 0, y: 0 }}
|
||||
end={{ x: 0, y: 1 }}
|
||||
>
|
||||
{state.routes.map((route, index) => {
|
||||
const { options } = descriptors[route.key];
|
||||
const isFocused = state.index === index;
|
||||
|
||||
const onPress = () => {
|
||||
const event = navigation.emit({
|
||||
type: 'tabPress',
|
||||
target: route.key,
|
||||
canPreventDefault: true,
|
||||
});
|
||||
|
||||
if (!isFocused && !event.defaultPrevented) {
|
||||
navigation.navigate(route.name);
|
||||
}
|
||||
};
|
||||
|
||||
const getIconName = (routeName: string, focused: boolean): keyof typeof Ionicons.glyphMap => {
|
||||
switch (routeName) {
|
||||
case 'index':
|
||||
return focused ? 'home' : 'home-outline';
|
||||
case 'goals':
|
||||
return focused ? 'trophy' : 'trophy-outline';
|
||||
case 'attendance':
|
||||
return focused ? 'calendar' : 'calendar-outline';
|
||||
case 'recommendations':
|
||||
return focused ? 'sparkles' : 'sparkles-outline';
|
||||
case 'profile':
|
||||
return focused ? 'person' : 'person-outline';
|
||||
default:
|
||||
return 'ellipse-outline';
|
||||
}
|
||||
};
|
||||
|
||||
// Animation for scale
|
||||
const scaleValue = React.useRef(new Animated.Value(1)).current;
|
||||
|
||||
React.useEffect(() => {
|
||||
Animated.spring(scaleValue, {
|
||||
toValue: isFocused ? 1.2 : 1,
|
||||
useNativeDriver: true,
|
||||
friction: 8,
|
||||
}).start();
|
||||
}, [isFocused]);
|
||||
|
||||
return (
|
||||
<TouchableOpacity
|
||||
key={index}
|
||||
accessibilityRole="button"
|
||||
accessibilityState={isFocused ? { selected: true } : {}}
|
||||
accessibilityLabel={options.tabBarAccessibilityLabel}
|
||||
testID={(options as any).tabBarTestID}
|
||||
onPress={onPress}
|
||||
style={styles.tabItem}
|
||||
activeOpacity={0.7}
|
||||
>
|
||||
<Animated.View style={{ transform: [{ scale: scaleValue }] }}>
|
||||
{isFocused ? (
|
||||
<LinearGradient
|
||||
colors={theme.gradients.primary}
|
||||
style={styles.iconContainer}
|
||||
>
|
||||
<Ionicons
|
||||
name={getIconName(route.name, true)}
|
||||
size={20}
|
||||
color="#fff"
|
||||
/>
|
||||
</LinearGradient>
|
||||
) : (
|
||||
<Ionicons
|
||||
name={getIconName(route.name, false)}
|
||||
size={24}
|
||||
color={theme.colors.gray500}
|
||||
/>
|
||||
)}
|
||||
</Animated.View>
|
||||
</TouchableOpacity>
|
||||
);
|
||||
})}
|
||||
</LinearGradient>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
position: 'absolute',
|
||||
bottom: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
alignItems: 'center',
|
||||
paddingBottom: Platform.OS === 'ios' ? 30 : 20,
|
||||
pointerEvents: 'box-none',
|
||||
},
|
||||
tabBar: {
|
||||
flexDirection: 'row',
|
||||
backgroundColor: 'rgba(255, 255, 255, 0.8)',
|
||||
borderRadius: 35,
|
||||
height: 70,
|
||||
width: width - 40,
|
||||
justifyContent: 'space-around',
|
||||
alignItems: 'center',
|
||||
borderWidth: 1,
|
||||
borderColor: 'rgba(255, 255, 255, 0.5)',
|
||||
paddingHorizontal: 10,
|
||||
},
|
||||
tabItem: {
|
||||
flex: 1,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
height: '100%',
|
||||
},
|
||||
iconContainer: {
|
||||
width: 40,
|
||||
height: 40,
|
||||
borderRadius: 20,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
shadowColor: theme.colors.primary,
|
||||
shadowOffset: { width: 0, height: 4 },
|
||||
shadowOpacity: 0.3,
|
||||
shadowRadius: 8,
|
||||
elevation: 4,
|
||||
},
|
||||
});
|
||||
Reference in new issue
Block a user