import React from 'react'; import { Pressable, StyleSheet, Text, View } from 'react-native'; import { useSafeAreaInsets } from 'react-native-safe-area-context'; import { Ionicons } from '@expo/vector-icons'; import { Tabs, useRouter } from 'expo-router'; import type { BottomTabBarProps } from '@react-navigation/bottom-tabs'; import { useT } from '@/i18n'; import { colors, fontSize, shadow, spacing } from '@/theme'; const FAB_SIZE = 58; /** Width reserved for the centre action button, flanked by two tabs a side. */ const FAB_SLOT = 84; const TAB_ICONS: Record = { index: 'home', search: 'search', expiring: 'time', profile: 'person', }; const TAB_LABEL_KEYS: Record = { index: 'tabs.home', search: 'tabs.search', expiring: 'tabs.expiring', profile: 'tabs.profile', }; function TabBar({ state, navigation }: BottomTabBarProps) { const insets = useSafeAreaInsets(); const router = useRouter(); const t = useT(); const renderTab = (routeName: string) => { const index = state.routes.findIndex((r) => r.name === routeName); if (index < 0) return ; const route = state.routes[index]; const focused = state.index === index; return ( { const event = navigation.emit({ type: 'tabPress', target: route.key, canPreventDefault: true, }); if (!focused && !event.defaultPrevented) navigation.navigate(route.name); }} > {t(TAB_LABEL_KEYS[routeName])} ); }; // Two tabs, action, two tabs: symmetric, so the button sits on the midpoint. return ( {renderTab('index')} {renderTab('search')} [styles.fab, pressed && { opacity: 0.9 }]} onPress={() => router.push('/upload')} accessibilityLabel={t('tabs.upload')} > {t('tabs.upload')} {renderTab('expiring')} {renderTab('profile')} ); } export default function TabsLayout() { return ( }> ); } const styles = StyleSheet.create({ bar: { backgroundColor: colors.surface, borderTopWidth: 1, borderTopColor: colors.border, paddingTop: spacing[2], ...shadow.sm, }, row: { flexDirection: 'row', alignItems: 'flex-end', paddingHorizontal: spacing[1] }, group: { flex: 1, flexDirection: 'row' }, tab: { flex: 1, alignItems: 'center', gap: 3, paddingVertical: 4 }, tabLabel: { fontSize: fontSize['2xs'], fontWeight: '600', color: colors.slate400 }, fabSlot: { width: FAB_SLOT, alignItems: 'center' }, fab: { width: FAB_SIZE, height: FAB_SIZE, borderRadius: FAB_SIZE / 2, backgroundColor: colors.teal600, alignItems: 'center', justifyContent: 'center', marginTop: -FAB_SIZE / 2, ...shadow.md, }, fabLabel: { fontSize: fontSize['2xs'], fontWeight: '600', color: colors.teal700, marginTop: 3 }, });