Pretty up code. Add all my default stuff that I like

This commit is contained in:
Gabriel Brown 2025-01-28 10:17:33 -06:00
parent 5a821fc6b5
commit 0dfb7f190d
20 changed files with 191 additions and 182 deletions

View File

@ -1,21 +1,23 @@
import { Tabs } from 'expo-router'; import { Tabs } from 'expo-router';
import React from 'react'; import React from 'react';
import { Platform } from 'react-native'; import { Platform } from 'react-native';
import { HapticTab } from '@/components/default/HapticTab';
import { HapticTab } from '@/components/HapticTab';
import { IconSymbol } from '@/components/ui/IconSymbol'; import { IconSymbol } from '@/components/ui/IconSymbol';
import TabBarBackground from '@/components/ui/TabBarBackground'; import TabBarBackground from '@/components/ui/TabBarBackground';
import { Colors } from '@/constants/Colors'; import { Colors } from '@/constants/Colors';
import { useColorScheme } from '@/hooks/useColorScheme'; import { useColorScheme } from '@/hooks/useColorScheme';
export default function TabLayout() { const TabLayout = () => {
const colorScheme = useColorScheme(); const scheme = useColorScheme() ?? 'dark';
return ( return (
<Tabs <Tabs
screenOptions={{ screenOptions={{
tabBarActiveTintColor: Colors[colorScheme ?? 'light'].tint, tabBarActiveTintColor: Colors[scheme].tint,
headerShown: false, headerShown: false,
headerStyle: {
backgroundColor: Colors[scheme].background,
},
tabBarButton: HapticTab, tabBarButton: HapticTab,
tabBarBackground: TabBarBackground, tabBarBackground: TabBarBackground,
tabBarStyle: Platform.select({ tabBarStyle: Platform.select({
@ -23,7 +25,11 @@ export default function TabLayout() {
// Use a transparent background on iOS to show the blur effect // Use a transparent background on iOS to show the blur effect
position: 'absolute', position: 'absolute',
}, },
default: {}, default: {
backgroundColor: Colors[scheme].background,
borderTopColor: Colors[scheme].tint,
borderTopWidth: 1,
},
}), }),
}} }}
> >
@ -35,12 +41,13 @@ export default function TabLayout() {
}} }}
/> />
<Tabs.Screen <Tabs.Screen
name='explore' name='settings'
options={{ options={{
title: 'Explore', title: 'Settings',
tabBarIcon: ({ color }) => <IconSymbol size={28} name='paperplane.fill' color={color} />, tabBarIcon: ({ color }) => <IconSymbol size={28} name='gearshape.fill' color={color} />,
}} }}
/> />
</Tabs> </Tabs>
); );
} };
export default TabLayout;

View File

@ -1,14 +1,12 @@
import { Image, StyleSheet, Platform } from 'react-native'; import { Image, StyleSheet, Platform } from 'react-native';
import ParallaxScrollView from '@/components/default/ParallaxScrollView';
import { ThemedText, ThemedView } from '@/components/theme/Theme';
import { HelloWave } from '@/components/HelloWave'; const HomeScreen = () => {
import ParallaxScrollView from '@/components/ParallaxScrollView';
import { ThemedText } from '@/components/ThemedText';
import { ThemedView } from '@/components/ThemedView';
export default function HomeScreen() {
return ( return (
<ParallaxScrollView <ParallaxScrollView
headerBackgroundColor={{ light: '#A1CEDC', dark: '#1D3D47' }} headerBackgroundColor={{ light: '#A1CEDC', dark: '#1D3D47' }}
headerHeight={200}
headerImage={ headerImage={
<Image <Image
source={require('@/assets/images/partial-react-logo.png')} source={require('@/assets/images/partial-react-logo.png')}
@ -18,7 +16,6 @@ export default function HomeScreen() {
> >
<ThemedView style={styles.titleContainer}> <ThemedView style={styles.titleContainer}>
<ThemedText type='title'>Welcome!</ThemedText> <ThemedText type='title'>Welcome!</ThemedText>
<HelloWave />
</ThemedView> </ThemedView>
<ThemedView style={styles.stepContainer}> <ThemedView style={styles.stepContainer}>
<ThemedText type='subtitle'>Step 1: Try it</ThemedText> <ThemedText type='subtitle'>Step 1: Try it</ThemedText>
@ -53,7 +50,8 @@ export default function HomeScreen() {
</ThemedView> </ThemedView>
</ParallaxScrollView> </ParallaxScrollView>
); );
} };
export default HomeScreen;
const styles = StyleSheet.create({ const styles = StyleSheet.create({
titleContainer: { titleContainer: {

View File

@ -1,27 +1,21 @@
import { StyleSheet, Image, Platform } from 'react-native'; import { StyleSheet, Image, Platform } from 'react-native';
import { Collapsible } from '@/components/default/Collapsible';
import { Collapsible } from '@/components/Collapsible'; import { ExternalLink } from '@/components/default/ExternalLink';
import { ExternalLink } from '@/components/ExternalLink'; import ParallaxScrollView from '@/components/default/ParallaxScrollView';
import ParallaxScrollView from '@/components/ParallaxScrollView'; import { ThemedText, ThemedView } from '@/components/theme/Theme';
import { ThemedText } from '@/components/ThemedText';
import { ThemedView } from '@/components/ThemedView';
import { IconSymbol } from '@/components/ui/IconSymbol'; import { IconSymbol } from '@/components/ui/IconSymbol';
export default function TabTwoScreen() { const TabTwoScreen = () => {
return ( return (
<ParallaxScrollView <ParallaxScrollView
headerBackgroundColor={{ light: '#D0D0D0', dark: '#353636' }} headerBackgroundColor={{ light: '#D0D0D0', dark: '#353636' }}
headerHeight={150}
headerImage={ headerImage={
<IconSymbol <IconSymbol size={200} color='#808080' name='gear.circle' style={styles.headerImage} />
size={310}
color='#808080'
name='chevron.left.forwardslash.chevron.right'
style={styles.headerImage}
/>
} }
> >
<ThemedView style={styles.titleContainer}> <ThemedView style={styles.titleContainer}>
<ThemedText type='title'>Explore</ThemedText> <ThemedText type='title'>Settings</ThemedText>
</ThemedView> </ThemedView>
<ThemedText>This app includes example code to help you get started.</ThemedText> <ThemedText>This app includes example code to help you get started.</ThemedText>
<Collapsible title='File-based routing'> <Collapsible title='File-based routing'>
@ -94,7 +88,8 @@ export default function TabTwoScreen() {
</Collapsible> </Collapsible>
</ParallaxScrollView> </ParallaxScrollView>
); );
} };
export default TabTwoScreen;
const styles = StyleSheet.create({ const styles = StyleSheet.create({
headerImage: { headerImage: {

View File

@ -1,22 +1,22 @@
import { Link, Stack } from 'expo-router'; import { Link, Stack } from 'expo-router';
import { StyleSheet } from 'react-native'; import { StyleSheet } from 'react-native';
import { ThemedText, ThemedView } from '@/components/theme/Theme';
import TextButton from '@/components/theme/buttons/TextButton';
import { ThemedText } from '@/components/ThemedText'; const NotFoundScreen = () => {
import { ThemedView } from '@/components/ThemedView';
export default function NotFoundScreen() {
return ( return (
<> <>
<Stack.Screen options={{ title: 'Oops!' }} /> <Stack.Screen options={{ title: 'Page not found' }} />
<ThemedView style={styles.container}> <ThemedView style={styles.container}>
<ThemedText type='title'>This screen doesn't exist.</ThemedText> <ThemedText type='title'>This screen doesn't exist.</ThemedText>
<Link href='/' style={styles.link}> <Link href='/'>
<ThemedText type='link'>Go to home screen!</ThemedText> <TextButton width={200} height={45} text='Go to home screen' fontSize={24} />
</Link> </Link>
</ThemedView> </ThemedView>
</> </>
); );
} };
export default NotFoundScreen;
const styles = StyleSheet.create({ const styles = StyleSheet.create({
container: { container: {
@ -25,8 +25,4 @@ const styles = StyleSheet.create({
justifyContent: 'center', justifyContent: 'center',
padding: 20, padding: 20,
}, },
link: {
marginTop: 15,
paddingVertical: 15,
},
}); });

View File

@ -5,14 +5,13 @@ import * as SplashScreen from 'expo-splash-screen';
import { StatusBar } from 'expo-status-bar'; import { StatusBar } from 'expo-status-bar';
import { useEffect } from 'react'; import { useEffect } from 'react';
import 'react-native-reanimated'; import 'react-native-reanimated';
import { useColorScheme } from '@/hooks/useColorScheme'; import { useColorScheme } from '@/hooks/useColorScheme';
// Prevent the splash screen from auto-hiding before asset loading is complete. // Prevent the splash screen from auto-hiding before asset loading is complete.
SplashScreen.preventAutoHideAsync(); SplashScreen.preventAutoHideAsync();
export default function RootLayout() { const RootLayout = () => {
const colorScheme = useColorScheme(); const scheme = useColorScheme() ?? 'dark';
const [loaded] = useFonts({ const [loaded] = useFonts({
SpaceMono: require('../assets/fonts/SpaceMono-Regular.ttf'), SpaceMono: require('../assets/fonts/SpaceMono-Regular.ttf'),
}); });
@ -28,7 +27,7 @@ export default function RootLayout() {
} }
return ( return (
<ThemeProvider value={colorScheme === 'dark' ? DarkTheme : DefaultTheme}> <ThemeProvider value={scheme === 'dark' ? DarkTheme : DefaultTheme}>
<Stack> <Stack>
<Stack.Screen name='(tabs)' options={{ headerShown: false }} /> <Stack.Screen name='(tabs)' options={{ headerShown: false }} />
<Stack.Screen name='+not-found' /> <Stack.Screen name='+not-found' />
@ -36,4 +35,5 @@ export default function RootLayout() {
<StatusBar style='auto' /> <StatusBar style='auto' />
</ThemeProvider> </ThemeProvider>
); );
} };
export default RootLayout;

View File

@ -1,40 +0,0 @@
import { useEffect } from 'react';
import { StyleSheet } from 'react-native';
import Animated, {
useSharedValue,
useAnimatedStyle,
withTiming,
withRepeat,
withSequence,
} from 'react-native-reanimated';
import { ThemedText } from '@/components/ThemedText';
export function HelloWave() {
const rotationAnimation = useSharedValue(0);
useEffect(() => {
rotationAnimation.value = withRepeat(
withSequence(withTiming(25, { duration: 150 }), withTiming(0, { duration: 150 })),
4, // Run the animation 4 times
);
}, []);
const animatedStyle = useAnimatedStyle(() => ({
transform: [{ rotate: `${rotationAnimation.value}deg` }],
}));
return (
<Animated.View style={animatedStyle}>
<ThemedText style={styles.text}>👋</ThemedText>
</Animated.View>
);
}
const styles = StyleSheet.create({
text: {
fontSize: 28,
lineHeight: 32,
marginTop: -6,
},
});

View File

@ -1,14 +0,0 @@
import { View, type ViewProps } from 'react-native';
import { useThemeColor } from '@/hooks/useThemeColor';
export type ThemedViewProps = ViewProps & {
lightColor?: string;
darkColor?: string;
};
export function ThemedView({ style, lightColor, darkColor, ...otherProps }: ThemedViewProps) {
const backgroundColor = useThemeColor({ light: lightColor, dark: darkColor }, 'background');
return <View style={[{ backgroundColor }, style]} {...otherProps} />;
}

View File

@ -1,10 +0,0 @@
import * as React from 'react';
import renderer from 'react-test-renderer';
import { ThemedText } from '../ThemedText';
it(`renders correctly`, () => {
const tree = renderer.create(<ThemedText>Snapshot test!</ThemedText>).toJSON();
expect(tree).toMatchSnapshot();
});

View File

@ -1,24 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`renders correctly 1`] = `
<Text
style={
[
{
"color": "#11181C",
},
{
"fontSize": 16,
"lineHeight": 24,
},
undefined,
undefined,
undefined,
undefined,
undefined,
]
}
>
Snapshot test!
</Text>
`;

View File

@ -1,15 +1,13 @@
import { PropsWithChildren, useState } from 'react'; import { PropsWithChildren, useState } from 'react';
import { StyleSheet, TouchableOpacity } from 'react-native'; import { StyleSheet, TouchableOpacity } from 'react-native';
import { ThemedText, ThemedView } from '@/components/theme/Theme';
import { ThemedText } from '@/components/ThemedText';
import { ThemedView } from '@/components/ThemedView';
import { IconSymbol } from '@/components/ui/IconSymbol'; import { IconSymbol } from '@/components/ui/IconSymbol';
import { Colors } from '@/constants/Colors'; import { Colors } from '@/constants/Colors';
import { useColorScheme } from '@/hooks/useColorScheme'; import { useColorScheme } from '@/hooks/useColorScheme';
export function Collapsible({ children, title }: PropsWithChildren & { title: string }) { export const Collapsible = ({ children, title }: PropsWithChildren & { title: string }) => {
const [isOpen, setIsOpen] = useState(false); const [isOpen, setIsOpen] = useState(false);
const theme = useColorScheme() ?? 'light'; const scheme = useColorScheme() ?? 'dark';
return ( return (
<ThemedView> <ThemedView>
@ -22,7 +20,7 @@ export function Collapsible({ children, title }: PropsWithChildren & { title: st
name='chevron.right' name='chevron.right'
size={18} size={18}
weight='medium' weight='medium'
color={theme === 'light' ? Colors.light.icon : Colors.dark.icon} color={scheme === 'light' ? Colors.light.icon : Colors.dark.icon}
style={{ transform: [{ rotate: isOpen ? '90deg' : '0deg' }] }} style={{ transform: [{ rotate: isOpen ? '90deg' : '0deg' }] }}
/> />
@ -31,7 +29,7 @@ export function Collapsible({ children, title }: PropsWithChildren & { title: st
{isOpen && <ThemedView style={styles.content}>{children}</ThemedView>} {isOpen && <ThemedView style={styles.content}>{children}</ThemedView>}
</ThemedView> </ThemedView>
); );
} };
const styles = StyleSheet.create({ const styles = StyleSheet.create({
heading: { heading: {

View File

@ -1,16 +1,16 @@
import { Link } from 'expo-router'; import { Link, RelativePathString } from 'expo-router';
import { openBrowserAsync } from 'expo-web-browser'; import { openBrowserAsync } from 'expo-web-browser';
import { type ComponentProps } from 'react'; import { type ComponentProps } from 'react';
import { Platform } from 'react-native'; import { Platform } from 'react-native';
type Props = Omit<ComponentProps<typeof Link>, 'href'> & { href: string }; type Props = Omit<ComponentProps<typeof Link>, 'href'> & { href: string };
export function ExternalLink({ href, ...rest }: Props) { export const ExternalLink = ({ href, ...rest }: Props) => {
return ( return (
<Link <Link
target='_blank' target='_blank'
{...rest} {...rest}
href={href} href={href as RelativePathString}
onPress={async (event) => { onPress={async (event) => {
if (Platform.OS !== 'web') { if (Platform.OS !== 'web') {
// Prevent the default behavior of linking to the default browser on native. // Prevent the default behavior of linking to the default browser on native.
@ -21,4 +21,4 @@ export function ExternalLink({ href, ...rest }: Props) {
}} }}
/> />
); );
} };

View File

@ -2,7 +2,7 @@ import { BottomTabBarButtonProps } from '@react-navigation/bottom-tabs';
import { PlatformPressable } from '@react-navigation/elements'; import { PlatformPressable } from '@react-navigation/elements';
import * as Haptics from 'expo-haptics'; import * as Haptics from 'expo-haptics';
export function HapticTab(props: BottomTabBarButtonProps) { export const HapticTab = (props: BottomTabBarButtonProps) => {
return ( return (
<PlatformPressable <PlatformPressable
{...props} {...props}
@ -15,4 +15,4 @@ export function HapticTab(props: BottomTabBarButtonProps) {
}} }}
/> />
); );
} };

View File

@ -6,8 +6,7 @@ import Animated, {
useAnimatedStyle, useAnimatedStyle,
useScrollViewOffset, useScrollViewOffset,
} from 'react-native-reanimated'; } from 'react-native-reanimated';
import { ThemedView } from '@/components/theme/Theme';
import { ThemedView } from '@/components/ThemedView';
import { useBottomTabOverflow } from '@/components/ui/TabBarBackground'; import { useBottomTabOverflow } from '@/components/ui/TabBarBackground';
import { useColorScheme } from '@/hooks/useColorScheme'; import { useColorScheme } from '@/hooks/useColorScheme';
@ -16,14 +15,16 @@ const HEADER_HEIGHT = 250;
type Props = PropsWithChildren<{ type Props = PropsWithChildren<{
headerImage: ReactElement; headerImage: ReactElement;
headerBackgroundColor: { dark: string; light: string }; headerBackgroundColor: { dark: string; light: string };
headerHeight?: number;
}>; }>;
export default function ParallaxScrollView({ const ParallaxScrollView = ({
children, children,
headerImage, headerImage,
headerBackgroundColor, headerBackgroundColor,
}: Props) { headerHeight = HEADER_HEIGHT,
const colorScheme = useColorScheme() ?? 'light'; }: Props) => {
const scheme = useColorScheme() ?? 'dark';
const scrollRef = useAnimatedRef<Animated.ScrollView>(); const scrollRef = useAnimatedRef<Animated.ScrollView>();
const scrollOffset = useScrollViewOffset(scrollRef); const scrollOffset = useScrollViewOffset(scrollRef);
const bottom = useBottomTabOverflow(); const bottom = useBottomTabOverflow();
@ -33,12 +34,12 @@ export default function ParallaxScrollView({
{ {
translateY: interpolate( translateY: interpolate(
scrollOffset.value, scrollOffset.value,
[-HEADER_HEIGHT, 0, HEADER_HEIGHT], [-headerHeight, 0, headerHeight],
[-HEADER_HEIGHT / 2, 0, HEADER_HEIGHT * 0.75], [-headerHeight / 2, 0, headerHeight * 0.75],
), ),
}, },
{ {
scale: interpolate(scrollOffset.value, [-HEADER_HEIGHT, 0, HEADER_HEIGHT], [2, 1, 1]), scale: interpolate(scrollOffset.value, [-headerHeight, 0, headerHeight], [2, 1, 1]),
}, },
], ],
}; };
@ -55,7 +56,10 @@ export default function ParallaxScrollView({
<Animated.View <Animated.View
style={[ style={[
styles.header, styles.header,
{ backgroundColor: headerBackgroundColor[colorScheme] }, {
backgroundColor: headerBackgroundColor[scheme],
height: headerHeight,
},
headerAnimatedStyle, headerAnimatedStyle,
]} ]}
> >
@ -65,14 +69,14 @@ export default function ParallaxScrollView({
</Animated.ScrollView> </Animated.ScrollView>
</ThemedView> </ThemedView>
); );
} };
export default ParallaxScrollView;
const styles = StyleSheet.create({ const styles = StyleSheet.create({
container: { container: {
flex: 1, flex: 1,
}, },
header: { header: {
height: HEADER_HEIGHT,
overflow: 'hidden', overflow: 'hidden',
}, },
content: { content: {

View File

@ -1,22 +1,30 @@
import { View, type ViewProps } from 'react-native';
import { Text, type TextProps, StyleSheet } from 'react-native'; import { Text, type TextProps, StyleSheet } from 'react-native';
import { useThemeColor } from '@/hooks/useThemeColor'; import { useThemeColor } from '@/hooks/useThemeColor';
export type ThemedViewProps = ViewProps & {
lightColor?: string;
darkColor?: string;
};
export type ThemedTextProps = TextProps & { export type ThemedTextProps = TextProps & {
lightColor?: string; lightColor?: string;
darkColor?: string; darkColor?: string;
type?: 'default' | 'title' | 'defaultSemiBold' | 'subtitle' | 'link'; type?: 'default' | 'title' | 'defaultSemiBold' | 'subtitle' | 'link';
}; };
export function ThemedText({ export const ThemedView = ({ style, lightColor, darkColor, ...otherProps }: ThemedViewProps) => {
const backgroundColor = useThemeColor({ light: lightColor, dark: darkColor }, 'background');
return <View style={[{ backgroundColor }, style]} {...otherProps} />;
};
export const ThemedText = ({
style, style,
lightColor, lightColor,
darkColor, darkColor,
type = 'default', type = 'default',
...rest ...rest
}: ThemedTextProps) { }: ThemedTextProps) => {
const color = useThemeColor({ light: lightColor, dark: darkColor }, 'text'); const color = useThemeColor({ light: lightColor, dark: darkColor }, 'text');
return ( return (
<Text <Text
style={[ style={[
@ -31,7 +39,7 @@ export function ThemedText({
{...rest} {...rest}
/> />
); );
} };
const styles = StyleSheet.create({ const styles = StyleSheet.create({
default: { default: {

View File

@ -0,0 +1,58 @@
import { StyleSheet, Pressable } from 'react-native';
import { ThemedView } from '@/components/theme/Theme';
import { Colors } from '@/constants/Colors';
import { useColorScheme } from '@/hooks/useColorScheme';
import { StyleProp, ViewStyle } from 'react-native';
const DEFAULT_WIDTH = 320;
const DEFAULT_HEIGHT = 68;
type Props = {
width?: number;
height?: number;
onPress?: () => void;
};
const Button = ({
width,
height,
children,
onPress,
}: Props & React.ComponentProps<typeof Pressable>) => {
const scheme = useColorScheme() ?? 'dark';
return (
<ThemedView
style={[
styles.buttonContainer,
{
width: width ?? DEFAULT_WIDTH,
height: height ?? DEFAULT_HEIGHT,
},
]}
>
<Pressable
style={[styles.button, { backgroundColor: Colors[scheme].text }]}
onPress={onPress}
>
{children}
</Pressable>
</ThemedView>
);
};
export default Button;
const styles = StyleSheet.create({
buttonContainer: {
alignItems: 'center',
justifyContent: 'center',
padding: 3,
},
button: {
borderRadius: 10,
width: '100%',
height: '100%',
alignItems: 'center',
justifyContent: 'center',
flexDirection: 'row',
},
});

View File

@ -0,0 +1,33 @@
import Button from '@/components/theme/buttons/Button';
import { ThemedText } from '@/components/theme/Theme';
import { Colors } from '@/constants/Colors';
import { useColorScheme } from '@/hooks/useColorScheme';
const DEFAULT_FONT_SIZE = 16;
type Props = {
width?: number;
height?: number;
text: string;
fontSize?: number;
onPress?: () => void;
};
const TextButton = ({ width, height, text, fontSize, onPress }: Props) => {
const scheme = useColorScheme() ?? 'dark';
return (
<Button width={width} height={height} onPress={onPress}>
<ThemedText
style={[
{
color: Colors[scheme].background,
fontSize: fontSize ?? DEFAULT_FONT_SIZE,
},
]}
>
{text}
</ThemedText>
</Button>
);
};
export default TextButton;

View File

@ -1,7 +1,7 @@
import { SymbolView, SymbolViewProps, SymbolWeight } from 'expo-symbols'; import { SymbolView, SymbolViewProps, SymbolWeight } from 'expo-symbols';
import { StyleProp, ViewStyle } from 'react-native'; import { StyleProp, ViewStyle } from 'react-native';
export function IconSymbol({ export const IconSymbol = ({
name, name,
size = 24, size = 24,
color, color,
@ -13,7 +13,7 @@ export function IconSymbol({
color: string; color: string;
style?: StyleProp<ViewStyle>; style?: StyleProp<ViewStyle>;
weight?: SymbolWeight; weight?: SymbolWeight;
}) { }) => {
return ( return (
<SymbolView <SymbolView
weight={weight} weight={weight}
@ -29,4 +29,4 @@ export function IconSymbol({
]} ]}
/> />
); );
} };

View File

@ -3,7 +3,7 @@
import MaterialIcons from '@expo/vector-icons/MaterialIcons'; import MaterialIcons from '@expo/vector-icons/MaterialIcons';
import { SymbolWeight } from 'expo-symbols'; import { SymbolWeight } from 'expo-symbols';
import React from 'react'; import React from 'react';
import { OpaqueColorValue, StyleProp, ViewStyle } from 'react-native'; import { OpaqueColorValue, StyleProp, TextStyle } from 'react-native';
// Add your SFSymbol to MaterialIcons mappings here. // Add your SFSymbol to MaterialIcons mappings here.
const MAPPING = { const MAPPING = {
@ -27,7 +27,7 @@ export type IconSymbolName = keyof typeof MAPPING;
* *
* Icon `name`s are based on SFSymbols and require manual mapping to MaterialIcons. * Icon `name`s are based on SFSymbols and require manual mapping to MaterialIcons.
*/ */
export function IconSymbol({ export const IconSymbol = ({
name, name,
size = 24, size = 24,
color, color,
@ -36,8 +36,8 @@ export function IconSymbol({
name: IconSymbolName; name: IconSymbolName;
size?: number; size?: number;
color: string | OpaqueColorValue; color: string | OpaqueColorValue;
style?: StyleProp<ViewStyle>; style?: StyleProp<TextStyle>;
weight?: SymbolWeight; weight?: SymbolWeight;
}) { }) => {
return <MaterialIcons color={color} size={size} name={MAPPING[name]} style={style} />; return <MaterialIcons color={color} size={size} name={MAPPING[name]} style={style} />;
} };

View File

@ -3,7 +3,7 @@ import { BlurView } from 'expo-blur';
import { StyleSheet } from 'react-native'; import { StyleSheet } from 'react-native';
import { useSafeAreaInsets } from 'react-native-safe-area-context'; import { useSafeAreaInsets } from 'react-native-safe-area-context';
export default function BlurTabBarBackground() { const BlurTabBarBackground = () => {
return ( return (
<BlurView <BlurView
// System chrome material automatically adapts to the system's theme // System chrome material automatically adapts to the system's theme
@ -13,10 +13,11 @@ export default function BlurTabBarBackground() {
style={StyleSheet.absoluteFill} style={StyleSheet.absoluteFill}
/> />
); );
} };
export default BlurTabBarBackground;
export function useBottomTabOverflow() { export const useBottomTabOverflow = () => {
const tabHeight = useBottomTabBarHeight(); const tabHeight = useBottomTabBarHeight();
const { bottom } = useSafeAreaInsets(); const { bottom } = useSafeAreaInsets();
return tabHeight - bottom; return tabHeight - bottom;
} };

View File

@ -1,6 +1,5 @@
// This is a shim for web and Android where the tab bar is generally opaque. // This is a shim for web and Android where the tab bar is generally opaque.
export default undefined; export default undefined;
export const useBottomTabOverflow = () => {
export function useBottomTabOverflow() {
return 0; return 0;
} };