Spaces:
Sleeping
Sleeping
Download TruthScan AI_frontend/components/NavBar.tsx from Bjornpool/truthscan-ai-backend: direct link, hf CLI and curl.
- Browser
- Download file 3.29 kB
-
https://huggingface.co/spaces/Bjornpool/truthscan-ai-backend/resolve/a7e77af2424a1608cd0f9013ccdf15d6e8e46c05/TruthScan%20AI_frontend/components/NavBar.tsx
- Command line
-
hf download 'hf://spaces/Bjornpool/truthscan-ai-backend@a7e77af2424a1608cd0f9013ccdf15d6e8e46c05/TruthScan AI_frontend/components/NavBar.tsx'
-
curl -L -o NavBar.tsx https://huggingface.co/spaces/Bjornpool/truthscan-ai-backend/resolve/a7e77af2424a1608cd0f9013ccdf15d6e8e46c05/TruthScan%20AI_frontend/components/NavBar.tsx
3.29 kB
| /** | |
| * Globalny komponent nawigacji aplikacji. | |
| * | |
| * Odpowiada za: | |
| * - prezentacj臋 g艂贸wnej nawigacji mi臋dzy widokami, | |
| * - obs艂ug臋 zmiany j臋zyka interfejsu (PL / EN), | |
| * - prze艂膮czanie trybu jasnego i ciemnego, | |
| * - wizualne wskazanie aktywnej trasy. | |
| */ | |
| "use client"; | |
| import { useEffect, useState } from "react"; | |
| import Link from "next/link"; | |
| import { usePathname } from "next/navigation"; | |
| import { motion } from "framer-motion"; | |
| import LanguageSwitcher from "./LanguageSwitcher"; | |
| import DarkModeToggle from "./DarkModeToggle"; | |
| type Lang = "pl" | "en" | "no"; | |
| export default function NavBar() { | |
| const pathname = usePathname(); | |
| const [language, setLanguage] = useState<Lang>("pl"); | |
| useEffect(() => { | |
| const stored = localStorage.getItem("lang"); | |
| if (stored === "pl" || stored === "en" || stored === "no") setLanguage(stored as Lang); | |
| }, []); | |
| useEffect(() => { | |
| localStorage.setItem("lang", language); | |
| if (typeof document !== "undefined") document.documentElement.lang = language; | |
| window.dispatchEvent(new CustomEvent("app:langchange", { detail: language })); | |
| }, [language]); | |
| const links = [ | |
| { href: "/", labelPl: "Strona g艂贸wna", labelEn: "Home", labelNo: "Hjem", icon: "馃彔" }, | |
| { href: "/dashboard", labelPl: "Dashboard", labelEn: "Dashboard", labelNo: "Dashbord", icon: "馃搳" }, | |
| { href: "/saved", labelPl: "Zapisane", labelEn: "Saved", labelNo: "Lagrede", icon: "馃捑" }, | |
| ]; | |
| return ( | |
| <nav className="sticky top-0 z-50 bg-gray-100 dark:bg-gray-900 shadow-md border-b border-gray-300/20 dark:border-gray-700/50"> | |
| <div className="w-full flex justify-between items-center px-4 md:px-6 h-14"> | |
| <div className="flex items-center gap-6"> | |
| <div | |
| className="hidden sm:block text-base font-semibold text-blue-600 dark:text-blue-400 select-none cursor-default" | |
| aria-label="TruthScan AI" | |
| role="img" | |
| > | |
| TruthScan AI | |
| </div> | |
| <div className="flex items-center gap-6 relative"> | |
| {links.map(({ href, labelPl, labelEn, labelNo, icon }) => { | |
| const active = pathname === href || (href !== "/" && pathname.startsWith(href)); | |
| return ( | |
| <div key={href} className="relative"> | |
| <Link href={href} className="inline-flex items-center gap-1.5"> | |
| {icon && ( | |
| <span | |
| aria-hidden="true" | |
| className="text-[18px] leading-none inline-block translate-y-[1px]" | |
| > | |
| {icon} | |
| </span> | |
| )} | |
| {language === "pl" ? labelPl : language === "no" ? labelNo : labelEn} | |
| </Link> | |
| {active && ( | |
| <motion.div | |
| layoutId="nav-indicator" | |
| className="absolute -bottom-1 left-0 right-0 h-[2px] bg-blue-600 dark:bg-blue-400 rounded-full" | |
| transition={{ type: "spring", stiffness: 400, damping: 30 }} | |
| /> | |
| )} | |
| </div> | |
| ); | |
| })} | |
| </div> | |
| </div> | |
| <div className="flex items-center gap-2"> | |
| <LanguageSwitcher language={language} setLanguage={setLanguage} /> | |
| <DarkModeToggle /> | |
| </div> | |
| </div> | |
| </nav> | |
| ); | |
| } | |