puzzle-trainer/components/BottomNav.tsx
2026-05-23 01:05:21 +00:00

89 lines
3.7 KiB
TypeScript

"use client";
import Link from "next/link";
import { usePathname } from "next/navigation";
const TABS = [
{
href: "/",
label: "Aujourd'hui",
icon: (active: boolean) => (
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={active ? 2.5 : 1.8} strokeLinecap="round" strokeLinejoin="round">
<rect x="3" y="4" width="18" height="18" rx="2"/>
<line x1="16" y1="2" x2="16" y2="6"/>
<line x1="8" y1="2" x2="8" y2="6"/>
<line x1="3" y1="10" x2="21" y2="10"/>
<path d="M8 14h.01M12 14h.01M16 14h.01M8 18h.01M12 18h.01" strokeWidth={2.5}/>
</svg>
),
},
{
href: "/levels",
label: "Entraînement",
icon: (active: boolean) => (
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={active ? 2.5 : 1.8} strokeLinecap="round" strokeLinejoin="round">
<path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"/>
</svg>
),
},
{
href: "/stats",
label: "Stats",
icon: (active: boolean) => (
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={active ? 2.5 : 1.8} strokeLinecap="round" strokeLinejoin="round">
<line x1="18" y1="20" x2="18" y2="10"/>
<line x1="12" y1="20" x2="12" y2="4"/>
<line x1="6" y1="20" x2="6" y2="14"/>
</svg>
),
},
{
href: "/settings",
label: "Réglages",
icon: (active: boolean) => (
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={active ? 2.5 : 1.8} strokeLinecap="round" strokeLinejoin="round">
<circle cx="12" cy="12" r="3"/>
<path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/>
</svg>
),
},
];
export default function BottomNav() {
const pathname = usePathname();
function isActive(href: string) {
if (href === "/") return pathname === "/";
if (href === "/levels") return pathname.includes("/levels") || pathname.includes("/level/");
return pathname.startsWith(href);
}
return (
<nav
className="fixed bottom-0 left-0 right-0 z-40 bg-white/95 backdrop-blur-xl border-t border-gray-100"
style={{ paddingBottom: "env(safe-area-inset-bottom)" }}
>
<div className="flex items-stretch h-14">
{TABS.map(tab => {
const active = isActive(tab.href);
return (
<Link
key={tab.href}
href={tab.href}
className="flex-1 flex flex-col items-center justify-center gap-0.5 transition-colors"
style={{ color: active ? "#111827" : "#9ca3af" }}
>
{tab.icon(active)}
<span className={`text-[9px] font-semibold tracking-tight leading-none ${active ? "text-gray-900" : "text-gray-400"}`}>
{tab.label}
</span>
{active && (
<span className="absolute bottom-0 w-8 h-0.5 bg-gray-900 rounded-t-full" style={{ marginBottom: "calc(env(safe-area-inset-bottom) + 2px)" }} />
)}
</Link>
);
})}
</div>
</nav>
);
}