83 lines
3.6 KiB
TypeScript
83 lines
3.6 KiB
TypeScript
|
|
import { ReactNode } from "react";
|
||
|
|
import { Link, Outlet, useLocation } from "react-router-dom";
|
||
|
|
import { Github, Twitter, Linkedin, Mail } from "lucide-react";
|
||
|
|
import { cn } from "../lib/utils";
|
||
|
|
import { motion } from "motion/react";
|
||
|
|
|
||
|
|
function NavLink({ to, children, active }: { to: string; children: ReactNode; active?: boolean }) {
|
||
|
|
return (
|
||
|
|
<Link
|
||
|
|
to={to}
|
||
|
|
className={cn(
|
||
|
|
"relative text-sm tracking-wide transition-colors hover:text-stone-900",
|
||
|
|
active ? "text-stone-900 font-medium" : "text-stone-500"
|
||
|
|
)}
|
||
|
|
>
|
||
|
|
{children}
|
||
|
|
{active && (
|
||
|
|
<motion.div
|
||
|
|
layoutId="nav-indicator"
|
||
|
|
className="absolute -bottom-[21px] left-0 right-0 h-[1px] bg-stone-900"
|
||
|
|
initial={false}
|
||
|
|
transition={{ type: "spring", stiffness: 500, damping: 30 }}
|
||
|
|
/>
|
||
|
|
)}
|
||
|
|
</Link>
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
export function RootLayout() {
|
||
|
|
const location = useLocation();
|
||
|
|
|
||
|
|
return (
|
||
|
|
<div className="min-h-screen bg-[#FDFBF7] font-sans text-stone-800 flex flex-col selection:bg-stone-200 selection:text-stone-900 print:bg-white print:text-stone-900">
|
||
|
|
{/* Header */}
|
||
|
|
<header className="sticky top-0 z-50 border-b border-stone-200/50 bg-[#FDFBF7]/80 backdrop-blur-xl print:hidden">
|
||
|
|
<div className="mx-auto max-w-5xl px-4 md:px-8 h-20 flex items-center justify-between">
|
||
|
|
<Link to="/" className="flex items-center gap-3">
|
||
|
|
<div className="w-10 h-10 rounded-xl bg-stone-900 text-[#FDFBF7] flex items-center justify-center font-serif italic text-2xl pb-1 shadow-sm">H</div>
|
||
|
|
<span className="text-xl font-serif italic font-medium tracking-tight text-stone-900 hidden sm:block">Helena.</span>
|
||
|
|
</Link>
|
||
|
|
|
||
|
|
<nav className="flex items-center gap-4 sm:gap-6">
|
||
|
|
<NavLink to="/" active={location.pathname === "/"}>Início</NavLink>
|
||
|
|
<NavLink to="/blog" active={location.pathname.startsWith("/blog")}>Artigos</NavLink>
|
||
|
|
<NavLink to="/curriculo" active={location.pathname === "/curriculo"}>Currículo</NavLink>
|
||
|
|
<NavLink to="/contato" active={location.pathname === "/contato"}>Contato</NavLink>
|
||
|
|
</nav>
|
||
|
|
</div>
|
||
|
|
</header>
|
||
|
|
|
||
|
|
{/* Main Content */}
|
||
|
|
<main className="flex-1 w-full max-w-5xl mx-auto px-4 md:px-8 py-12 md:py-24 print:py-0 print:px-0 print:max-w-none">
|
||
|
|
<Outlet />
|
||
|
|
</main>
|
||
|
|
|
||
|
|
{/* Footer */}
|
||
|
|
<footer className="border-t border-stone-200/50 py-16 text-stone-500 print:hidden mt-auto">
|
||
|
|
<div className="max-w-5xl mx-auto px-4 md:px-8 flex flex-col md:flex-row justify-between items-center gap-8">
|
||
|
|
<div className="flex flex-col items-center md:items-start gap-2">
|
||
|
|
<div className="w-8 h-8 rounded-lg bg-stone-200 text-stone-600 flex items-center justify-center font-serif italic text-xl pb-1">H</div>
|
||
|
|
<span className="text-sm font-serif italic text-stone-600">© {new Date().getFullYear()} Helena Costa. Direitos reservados.</span>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div className="flex gap-4">
|
||
|
|
<a href="#" className="hover:text-stone-900 transition-colors">
|
||
|
|
<Twitter className="w-4 h-4" />
|
||
|
|
</a>
|
||
|
|
<a href="#" className="hover:text-stone-900 transition-colors">
|
||
|
|
<Github className="w-4 h-4" />
|
||
|
|
</a>
|
||
|
|
<a href="#" className="hover:text-stone-900 transition-colors">
|
||
|
|
<Linkedin className="w-4 h-4" />
|
||
|
|
</a>
|
||
|
|
<a href="#" className="hover:text-stone-900 transition-colors">
|
||
|
|
<Mail className="w-4 h-4" />
|
||
|
|
</a>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</footer>
|
||
|
|
</div>
|
||
|
|
);
|
||
|
|
}
|