sentimind / src /components /Navbar.tsx
anggars's picture
Sync from GitHub Actions: 7c3c721754377a83f367deb89053391d29a38746
fd47a62 verified
"use client";
import Link from "next/link";
import { usePathname } from "next/navigation";
import { useTheme } from "next-themes";
import { useState, useEffect } from "react";
import { Sun, Moon, BrainCircuit, Menu, X } from "lucide-react";
import { useLanguage } from "@/app/providers";
import { Button } from "@/components/ui/button";
export default function Navbar() {
const { theme, setTheme } = useTheme();
const { lang, toggleLang } = useLanguage();
const pathname = usePathname();
const [isScrolled, setIsScrolled] = useState(false);
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);
const [mounted, setMounted] = useState(false);
useEffect(() => {
setMounted(true);
const handleScroll = () => setIsScrolled(window.scrollY > 20);
window.addEventListener("scroll", handleScroll);
return () => window.removeEventListener("scroll", handleScroll);
}, []);
const getLinkVariant = (path: string) =>
pathname === path ? "secondary" : "ghost";
const navLinks = [
{ href: "/", label: lang === "en" ? "Home" : "Beranda" },
{ href: "/analyzer", label: lang === "en" ? "Analyzer" : "Analisis" },
{ href: "/quiz", label: lang === "en" ? "Quiz" : "Kuis" },
{ href: "/types", label: lang === "en" ? "Types" : "Tipe" },
{ href: "/chat", label: lang === "en" ? "Chat" : "Chat" },
];
return (
<>
<nav
className={`
fixed left-1/2 -translate-x-1/2 z-50
flex justify-between items-center px-4 py-3
/* GANTI BAGIAN TRANSISI DI SINI: */
transition-all duration-700 ease-[cubic-bezier(0.25,0.1,0.25,1.0)] will-change-[width,top,background]
${
isScrolled
? /* SCROLLED STATE:
- top-4: Turun dikit
- w-[92%]: Lebar di layar kecil
- md:w-[48rem]: KUNCI ANIMASI! Pake w-[48rem] (sama dengan max-w-3xl) biar transisi width-nya mulus.
Jangan pake max-w-3xl karena bakal crash sama transisi width.
- rounded-[12px]: Jadi kotak tumpul
*/
"top-4 w-[92%] md:w-[48rem] rounded-[12px] bg-white/40 dark:bg-black/40 backdrop-blur-xl border border-gray-200 dark:border-white/10 shadow-sm"
: /* DEFAULT STATE:
- top-0: Nempel atas
- w-full: Lebar penuh
*/
"top-0 w-full bg-transparent border-b border-transparent"
}
`}
>
{/* LOGO */}
<Link href="/" className="flex items-center gap-2 pl-2">
<div className="bg-orange-600 p-1.5 rounded-[8px]">
<BrainCircuit className="text-white w-5 h-5" />
</div>
<span className="font-bold text-lg tracking-tight text-gray-900 dark:text-white">
Sentimind<span className="text-orange-600">.</span>
</span>
</Link>
{/* DESKTOP MENU */}
<div className="hidden md:flex items-center gap-1">
{navLinks.map((link) => (
<Button
key={link.href}
asChild
variant={getLinkVariant(link.href)}
size="sm"
className={`cursor-pointer text-sm font-medium ${
pathname === link.href
? "text-orange-600 dark:text-orange-400 bg-orange-50 dark:bg-orange-950/30"
: "text-gray-600 dark:text-gray-400"
}`}
>
<Link href={link.href}>{link.label}</Link>
</Button>
))}
</div>
{/* KANAN: Lang + Theme */}
<div className="flex items-center gap-2 pr-2">
<Button
onClick={toggleLang}
variant="ghost"
size="sm"
className="w-9 h-9 p-0 text-xs font-bold text-gray-500"
>
{lang.toUpperCase()}
</Button>
<Button
onClick={() => setTheme(theme === "dark" ? "light" : "dark")}
variant="ghost"
size="icon"
className="w-9 h-9 rounded-full text-gray-500"
>
{!mounted ? (
<div className="w-4 h-4" />
) : theme === "dark" ? (
<Sun className="w-4 h-4" />
) : (
<Moon className="w-4 h-4" />
)}
</Button>
{/* Mobile Menu Button */}
<div className="md:hidden">
<Button
variant="ghost"
size="icon"
onClick={() => setIsMobileMenuOpen(!isMobileMenuOpen)}
>
{isMobileMenuOpen ? (
<X className="w-5 h-5" />
) : (
<Menu className="w-5 h-5" />
)}
</Button>
</div>
</div>
</nav>
{/* MOBILE MENU */}
{isMobileMenuOpen && (
<div className="fixed inset-0 z-40 bg-white dark:bg-black pt-24 px-6 animate-in slide-in-from-top-10 fade-in duration-200">
<div className="flex flex-col gap-2">
{navLinks.map((link) => (
<Link
key={link.href}
href={link.href}
onClick={() => setIsMobileMenuOpen(false)}
>
<Button
variant="ghost"
size="lg"
className="w-full justify-start text-lg font-medium"
>
{link.label}
</Button>
</Link>
))}
</div>
</div>
)}
</>
);
}