This repository has been archived on 2026-08-11. You can view files and clone it, but cannot push or open issues or pull requests.
Gishen-Mob/components/ui/FloatingTabBar.tsx
kirukib 7310a349c5 Add Gishen mobile app with complete demo shopping and care flows.
Ship Expo Router screens, seeded stores, and polished UX so auth, shop, checkout, prescriptions, loyalty, family, and account processes work end-to-end offline.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-07 01:21:32 +03:00

141 lines
3.7 KiB
TypeScript

import { Ionicons } from "@expo/vector-icons";
import { Tabs } from "expo-router";
import { View } from "react-native";
import { useSafeAreaInsets } from "react-native-safe-area-context";
import { useTranslation } from "react-i18next";
import { Text } from "@/components/ui/Text";
import { colors, fonts, radii, shadows } from "@/lib/theme";
import { useCartStore } from "@/lib/stores/cartStore";
function TabIcon({
name,
focused,
badge,
}: {
name: keyof typeof Ionicons.glyphMap;
focused: boolean;
badge?: number;
}) {
return (
<View style={{ width: 46, height: 40, alignItems: "center", justifyContent: "center" }}>
<View
style={{
width: 40,
height: 32,
borderRadius: radii.pill,
alignItems: "center",
justifyContent: "center",
backgroundColor: focused ? colors.brandSoft : "transparent",
}}
>
<Ionicons
name={name}
size={20}
color={focused ? colors.brandText : colors.subtle}
/>
</View>
{badge ? (
<View
style={{
position: "absolute",
top: -2,
right: 2,
minWidth: 17,
height: 17,
paddingHorizontal: 4,
borderRadius: 9,
backgroundColor: colors.danger,
alignItems: "center",
justifyContent: "center",
borderWidth: 2,
borderColor: colors.surface,
}}
>
<Text variant="micro" color={colors.surface} style={{ fontSize: 9, lineHeight: 12 }}>
{badge > 9 ? "9+" : badge}
</Text>
</View>
) : null}
</View>
);
}
export function FloatingTabBar() {
const insets = useSafeAreaInsets();
const { t } = useTranslation();
const cartCount = useCartStore((s) => s.totalItems());
return (
<Tabs
screenOptions={{
headerShown: false,
tabBarActiveTintColor: colors.brandText,
tabBarInactiveTintColor: colors.subtle,
tabBarLabelStyle: {
fontFamily: fonts.semibold,
fontSize: 11,
marginTop: 2,
},
tabBarItemStyle: { paddingTop: 8 },
tabBarStyle: [
{
position: "absolute",
left: 16,
right: 16,
bottom: Math.max(insets.bottom, 12),
height: 68,
borderRadius: radii.xl,
backgroundColor: colors.surface,
borderTopWidth: 0,
borderWidth: 1,
borderColor: colors.line,
paddingBottom: 8,
},
shadows.md,
],
}}
>
<Tabs.Screen
name="index"
options={{
title: t("common.home"),
tabBarIcon: ({ focused }) => (
<TabIcon name={focused ? "home" : "home-outline"} focused={focused} />
),
}}
/>
<Tabs.Screen
name="favorites"
options={{
title: t("common.favorites"),
tabBarIcon: ({ focused }) => (
<TabIcon name={focused ? "heart" : "heart-outline"} focused={focused} />
),
}}
/>
<Tabs.Screen
name="cart"
options={{
title: t("common.cart"),
tabBarIcon: ({ focused }) => (
<TabIcon
name={focused ? "bag-handle" : "bag-handle-outline"}
focused={focused}
badge={cartCount}
/>
),
}}
/>
<Tabs.Screen
name="profile"
options={{
title: t("common.profile"),
tabBarIcon: ({ focused }) => (
<TabIcon name={focused ? "person" : "person-outline"} focused={focused} />
),
}}
/>
</Tabs>
);
}