Files
movies-diary/spa/src/components/bottom-tab-bar.tsx
Gabriel Kaszewski b9c0b10740 feat: add SPA, serve at /app/, update Dockerfile and README
- React + TanStack Router + shadcn/ui SPA under spa/
- serve spa/dist at /app/ with index.html fallback for client routing
- Dockerfile: node build stage for SPA, copy dist into runtime image
- README: document SPA, CORS_ORIGINS env var, architecture entry
- vite base set to /app/, manifest.json paths fixed
2026-06-04 04:20:15 +02:00

67 lines
2.5 KiB
TypeScript

import { Link, useMatchRoute } from "@tanstack/react-router"
import { useTranslation } from "react-i18next"
import { Home, Search, BookOpen, User } from "lucide-react"
import { cn } from "@/lib/utils"
export function BottomTabBar({ onLogTap }: { onLogTap: () => void }) {
const { t } = useTranslation()
const matchRoute = useMatchRoute()
const tabs = [
{ to: "/", icon: Home, label: t("nav.home") },
{ to: "/search", icon: Search, label: t("nav.search") },
{ to: "/diary", icon: BookOpen, label: t("nav.diary") },
{ to: "/profile", icon: User, label: t("nav.profile") },
] as const
return (
<nav className="glass-heavy fixed bottom-0 left-0 right-0 z-50 border-t border-border pb-[env(safe-area-inset-bottom)]">
<div className="mx-auto flex max-w-lg items-center justify-around px-2 py-1">
{tabs.slice(0, 2).map((tab) => {
const active = matchRoute({ to: tab.to, fuzzy: tab.to !== "/" })
return (
<Link
key={tab.to}
to={tab.to}
className={cn(
"flex flex-col items-center gap-0.5 px-3 py-1.5 transition-colors",
active ? "text-foreground" : "text-muted-foreground",
)}
>
<tab.icon className="size-5" strokeWidth={active ? 2.5 : 2} />
<span className="text-[10px] font-medium">{tab.label}</span>
</Link>
)
})}
{/* Center FAB */}
<button
onClick={onLogTap}
className="flex flex-col items-center gap-0.5 px-3 py-1.5"
>
<div className="-mt-4 flex size-11 items-center justify-center rounded-full bg-primary text-primary-foreground shadow-lg shadow-primary/30 transition-transform active:scale-90">
<span className="text-xl font-light">+</span>
</div>
</button>
{tabs.slice(2).map((tab) => {
const active = matchRoute({ to: tab.to, fuzzy: true })
return (
<Link
key={tab.to}
to={tab.to}
className={cn(
"flex flex-col items-center gap-0.5 px-3 py-1.5 transition-colors",
active ? "text-foreground" : "text-muted-foreground",
)}
>
<tab.icon className="size-5" strokeWidth={active ? 2.5 : 2} />
<span className="text-[10px] font-medium">{tab.label}</span>
</Link>
)
})}
</div>
</nav>
)
}