"use client";
import { motion } from "framer-motion";
import { useAppReducedMotion as useReducedMotion } from "@/lib/motion-pref";
import Link from "next/link";
import { usePathname } from "next/navigation";
import { CompassIcon, FlameIcon, GearIcon, HomeIcon, PlusIcon } from "@/components/icons";
import { haptic } from "@/lib/haptics";
import { useI18n } from "@/lib/i18n";
import { springSnappy } from "@/lib/motion";
import { openSettings } from "@/lib/ui-events";
import { cn } from "@/lib/utils";
/**
* iOS-style bottom tab bar, phones only: Library · Progress · New deck (the
* prominent centre button) · Exam mode · Settings. The active item sits on a
* sliding pill (shared `layoutId`) and its icon gives a small bounce when you
* land on it; re-tapping the active tab scrolls back to the top.
*
* Labels use the short `tab.*` keys so they fit on one line at 360px in both
* languages — no ellipsis, no wrapping.
*/
export function TabBar() {
const pathname = usePathname();
const { t } = useI18n();
const reduceMotion = useReducedMotion();
/* The wizards keep their own bottom action bar (Cancel / Next / Freeze) and
chat keeps its own composer — the flow is deliberately focused, so the tab
bar steps aside there. */
const inWizard = pathname === "/create" || pathname === "/homework" || pathname === "/chat";
const item =
"relative flex min-h-[52px] min-w-0 flex-1 flex-col items-center justify-center gap-1 py-2 text-[10.5px] font-medium leading-none transition-colors";
const active = "text-[var(--text)]";
const idle = "text-[var(--text-subtle)]";
/** The pill glides between items; hidden under reduced motion. */
const pill = (isActive: boolean) =>
isActive && !reduceMotion ? (
) : null;
/** Small icon bounce on the item you just selected. */
const icon = (children: React.ReactNode, isActive: boolean, key: string) => (
{children}
);
const label = (text: string, isActive: boolean) => (
{text}
);
const isActive = (key: "library" | "progress" | "create" | "exam") => {
if (key === "library") return pathname === "/";
if (key === "progress") return pathname === "/stats";
// The homework wizard is the other half of the New deck screen.
if (key === "create") return pathname === "/create" || pathname === "/homework";
return pathname === "/exam";
};
const link = (
key: "library" | "progress" | "create" | "exam",
href: string,
labelText: string,
iconNode: React.ReactNode,
) => {
const current = isActive(key);
return (
{
haptic("tap");
// Re-tapping the active tab scrolls back to the top.
if (current) {
event.preventDefault();
window.scrollTo({ top: 0, behavior: reduceMotion ? "auto" : "smooth" });
}
}}
>
{pill(current)}
{icon(iconNode, current, key)}
{label(labelText, current)}
);
};
if (inWizard) return null;
return (
);
}