CodeIssuesDiscussionsWikiPull RequestsProjectsCommitsActionsReleasesContributorsPulse● GatesSecuritySettingsDeploymentsPipelineInsightsAgents✨ Explain✨ Ask AI✨ Workspace✨ Spec✨ Tests▓ Debt Map✨ NL Search🏛 Archaeology
Blame · Line-by-line history
MainTabNavigator.tsx
Each line is annotated with the commit that last touched it. Click any SHA to jump to that commit and see the surrounding change.
| c53cf00 | 1 | import React from 'react'; |
| 2 | import { createBottomTabNavigator } from '@react-navigation/bottom-tabs'; | |
| 3 | import { createNativeStackNavigator } from '@react-navigation/native-stack'; | |
| 9d7a803 | 4 | import { Text } from 'react-native'; |
| c53cf00 | 5 | import { colors } from '../theme/colors'; |
| 6 | import { fontSizes } from '../theme/typography'; | |
| 9d7a803 | 7 | import { type MainStackParamList } from './types'; |
| 8 | ||
| 9 | // Re-export for convenience (navigators that don't import screens can still get the type) | |
| 10 | export type { MainStackParamList }; | |
| c53cf00 | 11 | |
| 12 | import { DashboardScreen } from '../screens/DashboardScreen'; | |
| 13 | import { RepoListScreen } from '../screens/RepoListScreen'; | |
| 14 | import { RepoDetailScreen } from '../screens/RepoDetailScreen'; | |
| 15 | import { FileViewerScreen } from '../screens/FileViewerScreen'; | |
| 16 | import { IssueListScreen } from '../screens/IssueListScreen'; | |
| 17 | import { IssueDetailScreen } from '../screens/IssueDetailScreen'; | |
| 18 | import { PullListScreen } from '../screens/PullListScreen'; | |
| 19 | import { PullDetailScreen } from '../screens/PullDetailScreen'; | |
| 20 | import { NotificationsScreen } from '../screens/NotificationsScreen'; | |
| 21 | import { SettingsScreen } from '../screens/SettingsScreen'; | |
| 22 | ||
| 23 | const Stack = createNativeStackNavigator<MainStackParamList>(); | |
| 24 | const Tab = createBottomTabNavigator(); | |
| 25 | ||
| 26 | // ─── Stack navigators (one per tab root) ──────────────────────────────────── | |
| 27 | ||
| 28 | function DashboardStack() { | |
| 29 | return ( | |
| 30 | <Stack.Navigator screenOptions={stackScreenOptions}> | |
| 31 | <Stack.Screen name="Dashboard" component={DashboardScreen} options={{ title: 'Dashboard' }} /> | |
| 32 | <Stack.Screen name="RepoDetail" component={RepoDetailScreen} options={({ route }) => ({ title: route.params.repo })} /> | |
| 33 | <Stack.Screen name="FileViewer" component={FileViewerScreen} options={({ route }) => ({ title: route.params.path.split('/').pop() ?? 'File' })} /> | |
| 34 | <Stack.Screen name="IssueList" component={IssueListScreen} options={{ title: 'Issues' }} /> | |
| 35 | <Stack.Screen name="IssueDetail" component={IssueDetailScreen} options={({ route }) => ({ title: `#${route.params.number}` })} /> | |
| 36 | <Stack.Screen name="PullList" component={PullListScreen} options={{ title: 'Pull Requests' }} /> | |
| 37 | <Stack.Screen name="PullDetail" component={PullDetailScreen} options={({ route }) => ({ title: `PR #${route.params.number}` })} /> | |
| 38 | {/* Dummy screens required by type — never actually navigated to from this stack */} | |
| 39 | <Stack.Screen name="RepoList" component={RepoListScreen} options={{ title: 'Repositories' }} /> | |
| 40 | </Stack.Navigator> | |
| 41 | ); | |
| 42 | } | |
| 43 | ||
| 44 | function RepoStack() { | |
| 45 | return ( | |
| 46 | <Stack.Navigator screenOptions={stackScreenOptions}> | |
| 47 | <Stack.Screen name="RepoList" component={RepoListScreen} options={{ title: 'Repositories' }} /> | |
| 48 | <Stack.Screen name="RepoDetail" component={RepoDetailScreen} options={({ route }) => ({ title: route.params.repo })} /> | |
| 49 | <Stack.Screen name="FileViewer" component={FileViewerScreen} options={({ route }) => ({ title: route.params.path.split('/').pop() ?? 'File' })} /> | |
| 50 | <Stack.Screen name="IssueList" component={IssueListScreen} options={{ title: 'Issues' }} /> | |
| 51 | <Stack.Screen name="IssueDetail" component={IssueDetailScreen} options={({ route }) => ({ title: `#${route.params.number}` })} /> | |
| 52 | <Stack.Screen name="PullList" component={PullListScreen} options={{ title: 'Pull Requests' }} /> | |
| 53 | <Stack.Screen name="PullDetail" component={PullDetailScreen} options={({ route }) => ({ title: `PR #${route.params.number}` })} /> | |
| 54 | {/* Dummy — needed to satisfy shared type */} | |
| 55 | <Stack.Screen name="Dashboard" component={DashboardScreen} options={{ title: 'Dashboard' }} /> | |
| 56 | </Stack.Navigator> | |
| 57 | ); | |
| 58 | } | |
| 59 | ||
| 60 | // ─── Tab navigator ─────────────────────────────────────────────────────────── | |
| 61 | ||
| 62 | export function MainTabNavigator() { | |
| 63 | return ( | |
| 64 | <Tab.Navigator | |
| 65 | screenOptions={{ | |
| 66 | headerShown: false, | |
| 67 | tabBarStyle: { | |
| 68 | backgroundColor: colors.bgSecondary, | |
| 69 | borderTopColor: colors.border, | |
| 70 | borderTopWidth: 1, | |
| 71 | height: 60, | |
| 72 | paddingBottom: 8, | |
| 73 | }, | |
| 74 | tabBarActiveTintColor: colors.accent, | |
| 75 | tabBarInactiveTintColor: colors.textMuted, | |
| 76 | tabBarLabelStyle: { | |
| 77 | fontSize: fontSizes.xs, | |
| 78 | fontWeight: '500', | |
| 79 | }, | |
| 80 | }} | |
| 81 | > | |
| 82 | <Tab.Screen | |
| 83 | name="DashboardTab" | |
| 84 | component={DashboardStack} | |
| 85 | options={{ | |
| 86 | title: 'Dashboard', | |
| 87 | tabBarIcon: ({ color }) => <TabIcon icon="⌂" color={color} />, | |
| 88 | }} | |
| 89 | /> | |
| 90 | <Tab.Screen | |
| 91 | name="ReposTab" | |
| 92 | component={RepoStack} | |
| 93 | options={{ | |
| 94 | title: 'Repos', | |
| 95 | tabBarIcon: ({ color }) => <TabIcon icon="⌥" color={color} />, | |
| 96 | }} | |
| 97 | /> | |
| 98 | <Tab.Screen | |
| 99 | name="NotificationsTab" | |
| 100 | component={NotificationsScreen} | |
| 101 | options={{ | |
| 102 | title: 'Notifications', | |
| 103 | tabBarIcon: ({ color }) => <TabIcon icon="◉" color={color} />, | |
| 104 | }} | |
| 105 | /> | |
| 106 | <Tab.Screen | |
| 107 | name="SettingsTab" | |
| 108 | component={SettingsScreen} | |
| 109 | options={{ | |
| 110 | title: 'Settings', | |
| 111 | tabBarIcon: ({ color }) => <TabIcon icon="⚙" color={color} />, | |
| 112 | }} | |
| 113 | /> | |
| 114 | </Tab.Navigator> | |
| 115 | ); | |
| 116 | } | |
| 117 | ||
| 118 | // ─── Helpers ───────────────────────────────────────────────────────────────── | |
| 119 | ||
| 120 | function TabIcon({ icon, color }: { icon: string; color: string }) { | |
| 121 | return ( | |
| 122 | <Text style={{ fontSize: 18, color, lineHeight: 22 }}>{icon}</Text> | |
| 123 | ); | |
| 124 | } | |
| 125 | ||
| 126 | const stackScreenOptions = { | |
| 127 | headerStyle: { backgroundColor: colors.bgSecondary }, | |
| 128 | headerTintColor: colors.text, | |
| 129 | headerTitleStyle: { color: colors.text, fontWeight: '600' as const }, | |
| 130 | headerBackTitleVisible: false, | |
| 131 | contentStyle: { backgroundColor: colors.bg }, | |
| 132 | }; |