Files
2026-08-01 16:07:57 +02:00

98 lines
3.4 KiB
TypeScript

"use client";
import { useState, useEffect } from "react";
import Link from "next/link";
import { usePathname } from "next/navigation";
import { motion, AnimatePresence } from "framer-motion";
import { X, Globe } from "lucide-react";
import { localeFlags, type Locale, type Dictionary } from "@/lib/dictionaries";
interface LangBannerProps {
locale: Locale;
dict: Dictionary;
}
export default function LangBanner({ locale, dict }: LangBannerProps) {
const [show, setShow] = useState(false);
const pathname = usePathname();
const otherLocale: Locale = locale === "en" ? "sr" : "en";
useEffect(() => {
// Don't show if user already dismissed
if (document.cookie.includes("lang-banner-dismissed=1")) return;
// Check browser language
const browserLangs = navigator.languages || [navigator.language];
const prefersOther = browserLangs.some((lang) => {
const base = lang.toLowerCase().split("-")[0];
if (locale === "en" && ["sr", "bs", "hr"].includes(base)) return true;
if (locale === "sr" && base === "en") return true;
return false;
});
if (prefersOther) {
// Small delay so it doesn't flash on load
const timer = setTimeout(() => setShow(true), 1500);
return () => clearTimeout(timer);
}
}, [locale]);
useEffect(() => {
document.body.style.setProperty("--banner-h", show ? "40px" : "0px");
return () => { document.body.style.setProperty("--banner-h", "0px"); };
}, [show]);
function dismiss() {
setShow(false);
// Dismiss for 30 days
document.cookie = "lang-banner-dismissed=1; path=/; max-age=2592000; SameSite=Lax";
}
function getOtherLocalePath() {
const segments = pathname.split("/");
segments[1] = otherLocale;
return segments.join("/") || `/${otherLocale}`;
}
return (
<AnimatePresence>
{show && (
<motion.div
initial={{ height: 0, opacity: 0 }}
animate={{ height: "auto", opacity: 1 }}
exit={{ height: 0, opacity: 0 }}
transition={{ duration: 0.3, ease: [0.16, 1, 0.3, 1] }}
className="fixed inset-x-0 top-0 z-[60] overflow-hidden"
>
<div className="flex items-center justify-center gap-3 border-b border-purple-400/20 bg-purple-500/10 px-4 py-2.5 text-sm backdrop-blur-xl">
<Globe className="h-3.5 w-3.5 text-purple-300" strokeWidth={1.5} />
<span className="text-text-secondary">
{dict.langBanner.message}{" "}
<Link
href={getOtherLocalePath()}
onClick={() => {
// Set cookie so future root visits go to this locale
document.cookie = `NEXT_LOCALE=${otherLocale}; path=/; max-age=31536000; SameSite=Lax`;
dismiss();
}}
className="font-medium text-purple-300 underline decoration-purple-400/40 underline-offset-2 transition-colors hover:text-purple-200"
>
{localeFlags[otherLocale]} {dict.langBanner.switchTo}
</Link>
</span>
<button
type="button"
onClick={dismiss}
className="ml-2 rounded-md p-1 text-text-secondary transition-colors hover:bg-white/5 hover:text-text-primary"
aria-label="Dismiss"
>
<X className="h-3.5 w-3.5" />
</button>
</div>
</motion.div>
)}
</AnimatePresence>
);
}