import { Ionicons } from '@expo/vector-icons'; import { View, Text, Pressable } from 'react-native'; import { useTheme } from './useTheme'; export type TabDef = { key: K; label: string; icon: keyof typeof Ionicons.glyphMap; /** Small count shown after the label — peers, connections. Hidden when 0 or undefined. */ badge?: number; }; /** * A segmented control for a screen with a handful of sections. * * Pills rather than the dropdown Photos uses: that screen has six sections and a picker keeps the * chrome down, but with three, a dropdown hides two of them behind a tap and states the obvious. * Everything fits on one row here, so the sections are visible and one tap away. * * Sized for thumbs — 44pt is Apple's minimum target and the reason this is not a compact row of text. * * Deliberately NOT a navigator. These are sections of one screen sharing one view-model; a navigator * would give each its own mount lifecycle and remount the tunnel status on every switch. */ export const Tabs = ({ tabs, value, onChange, }: { tabs: readonly TabDef[]; value: K; onChange: (k: K) => void; }) => { const { palette } = useTheme(); return ( {tabs.map((t) => { const active = t.key === value; return ( onChange(t.key)} accessibilityRole="tab" accessibilityState={{ selected: active }} className="flex-1 flex-row items-center justify-center gap-1.5 rounded-xl active:opacity-70" style={{ minHeight: 44, // The brand yellow carries its own ink, because palette.text is near-white in dark mode // and unreadable on it. backgroundColor: active ? palette.brand : 'transparent', }} > {t.label} {t.badge ? ( {t.badge} ) : null} ); })} ); };