feat: navigation foundation with Expo Router tabs (v1.0.2)

This commit is contained in:
null 2026-05-13 16:17:09 -05:00
parent 1a1357d5c9
commit 01751c6f66
11 changed files with 1533 additions and 35 deletions

View File

@ -25,6 +25,9 @@
}, },
"web": { "web": {
"favicon": "./assets/favicon.png" "favicon": "./assets/favicon.png"
} },
"plugins": [
"expo-router"
]
} }
} }

37
app/(tabs)/_layout.tsx Normal file
View File

@ -0,0 +1,37 @@
import { Tabs } from 'expo-router';
import { Home, MessageCircle, Star, Settings } from 'lucide-react-native';
export default function TabsLayout() {
return (
<Tabs>
<Tabs.Tab
name="index"
options={{
title: 'Home',
tabBarIcon: ({ color }) => <Home color={color} size={24} />,
}}
/>
<Tabs.Tab
name="questions"
options={{
title: 'Questions',
tabBarIcon: ({ color }) => <MessageCircle color={color} size={24} />,
}}
/>
<Tabs.Tab
name="milestones"
options={{
title: 'Milestones',
tabBarIcon: ({ color }) => <Star color={color} size={24} />,
}}
/>
<Tabs.Tab
name="settings"
options={{
title: 'Settings',
tabBarIcon: ({ color }) => <Settings color={color} size={24} />,
}}
/>
</Tabs>
);
}

22
app/(tabs)/index.tsx Normal file
View File

@ -0,0 +1,22 @@
import { View, Text } from 'react-native';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
export default function HomeScreen() {
const insets = useSafeAreaInsets();
return (
<View
style={{
flex: 1,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#fff',
paddingTop: insets.top,
paddingBottom: insets.bottom,
paddingLeft: insets.left,
paddingRight: insets.right,
}}
>
<Text className="text-2xl font-bold text-gray-900">Home</Text>
</View>
);
}

22
app/(tabs)/milestones.tsx Normal file
View File

@ -0,0 +1,22 @@
import { View, Text } from 'react-native';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
export default function MilestonesScreen() {
const insets = useSafeAreaInsets();
return (
<View
style={{
flex: 1,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#fff',
paddingTop: insets.top,
paddingBottom: insets.bottom,
paddingLeft: insets.left,
paddingRight: insets.right,
}}
>
<Text className="text-2xl font-bold text-gray-900">Milestones</Text>
</View>
);
}

22
app/(tabs)/questions.tsx Normal file
View File

@ -0,0 +1,22 @@
import { View, Text } from 'react-native';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
export default function QuestionsScreen() {
const insets = useSafeAreaInsets();
return (
<View
style={{
flex: 1,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#fff',
paddingTop: insets.top,
paddingBottom: insets.bottom,
paddingLeft: insets.left,
paddingRight: insets.right,
}}
>
<Text className="text-2xl font-bold text-gray-900">Questions</Text>
</View>
);
}

22
app/(tabs)/settings.tsx Normal file
View File

@ -0,0 +1,22 @@
import { View, Text } from 'react-native';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
export default function SettingsScreen() {
const insets = useSafeAreaInsets();
return (
<View
style={{
flex: 1,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#fff',
paddingTop: insets.top,
paddingBottom: insets.bottom,
paddingLeft: insets.left,
paddingRight: insets.right,
}}
>
<Text className="text-2xl font-bold text-gray-900">Settings</Text>
</View>
);
}

22
app/[id].tsx Normal file
View File

@ -0,0 +1,22 @@
import { View, Text } from 'react-native';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
export default function DetailScreen() {
const insets = useSafeAreaInsets();
return (
<View
style={{
flex: 1,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#fff',
paddingTop: insets.top,
paddingBottom: insets.bottom,
paddingLeft: insets.left,
paddingRight: insets.right,
}}
>
<Text className="text-2xl font-bold text-gray-900">Detail</Text>
</View>
);
}

View File

@ -3,7 +3,8 @@ import { Stack } from 'expo-router';
export default function RootLayout() { export default function RootLayout() {
return ( return (
<Stack> <Stack>
<Stack.Screen name="index" /> <Stack.Screen name="(tabs)" />
<Stack.Screen name="index" options={{ headerShown: false }} />
</Stack> </Stack>
); );
} }

View File

@ -1,9 +0,0 @@
import { Text, View } from 'react-native';
export default function HomeScreen() {
return (
<View className="flex-1 items-center justify-center bg-white">
<Text className="text-2xl font-bold text-gray-900">Hello, Relationship App!</Text>
</View>
);
}

1390
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
{ {
"name": "relationship-app", "name": "relationship-app",
"version": "1.0.1", "version": "1.0.2",
"main": "index.ts", "main": "expo-router/entry",
"scripts": { "scripts": {
"start": "expo start", "start": "expo start",
"android": "expo start --android", "android": "expo start --android",
@ -10,9 +10,17 @@
}, },
"dependencies": { "dependencies": {
"expo": "~54.0.33", "expo": "~54.0.33",
"expo-constants": "~18.0.13",
"expo-linear-gradient": "~15.0.8",
"expo-linking": "~8.0.12",
"expo-router": "~6.0.23",
"expo-status-bar": "~3.0.9", "expo-status-bar": "~3.0.9",
"lucide-react-native": "^1.14.0",
"react": "19.1.0", "react": "19.1.0",
"react-native": "0.81.5" "react-native": "0.81.5",
"react-native-safe-area-context": "~5.6.0",
"react-native-screens": "~4.16.0",
"react-native-svg": "15.12.1"
}, },
"devDependencies": { "devDependencies": {
"@types/react": "~19.1.0", "@types/react": "~19.1.0",