feat: add Navbar, Footer, and LanguageSwitcher layout components

Install framer-motion and create shared layout components with i18n
support. Update locale layout to include fixed navbar, flex-col body,
and footer.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
consultoria-as
2026-02-22 03:58:03 +00:00
parent bd222376bd
commit dfda08085b
6 changed files with 96 additions and 2 deletions

View File

@@ -10,6 +10,7 @@
}, },
"dependencies": { "dependencies": {
"@afterlife/shared": "*", "@afterlife/shared": "*",
"framer-motion": "^12.34.3",
"next": "^15", "next": "^15",
"next-intl": "^4.8.3", "next-intl": "^4.8.3",
"react": "^19", "react": "^19",

View File

@@ -3,6 +3,8 @@ import { NextIntlClientProvider } from "next-intl";
import { getMessages } from "next-intl/server"; import { getMessages } from "next-intl/server";
import { notFound } from "next/navigation"; import { notFound } from "next/navigation";
import { routing } from "@/i18n/routing"; import { routing } from "@/i18n/routing";
import { Navbar } from "@/components/layout/Navbar";
import { Footer } from "@/components/layout/Footer";
import "./globals.css"; import "./globals.css";
export const metadata: Metadata = { export const metadata: Metadata = {
@@ -25,9 +27,11 @@ export default async function LocaleLayout({
return ( return (
<html lang={locale}> <html lang={locale}>
<body> <body className="bg-gray-950 text-white min-h-screen flex flex-col">
<NextIntlClientProvider messages={messages}> <NextIntlClientProvider messages={messages}>
{children} <Navbar />
<main className="flex-1 pt-16">{children}</main>
<Footer />
</NextIntlClientProvider> </NextIntlClientProvider>
</body> </body>
</html> </html>

View File

@@ -0,0 +1,13 @@
import { useTranslations } from "next-intl";
export function Footer() {
const t = useTranslations("footer");
return (
<footer className="bg-black border-t border-white/10 py-8">
<div className="max-w-7xl mx-auto px-4 text-center">
<p className="text-sm text-gray-500">{t("rights")}</p>
</div>
</footer>
);
}

View File

@@ -0,0 +1,36 @@
"use client";
import { useLocale, useTranslations } from "next-intl";
import { useRouter, usePathname } from "next/navigation";
export function LanguageSwitcher() {
const locale = useLocale();
const router = useRouter();
const pathname = usePathname();
const t = useTranslations("footer");
function switchLocale(newLocale: string) {
const segments = pathname.split("/");
segments[1] = newLocale;
router.push(segments.join("/"));
}
return (
<div className="flex items-center gap-2">
<span className="text-sm text-gray-400">{t("language")}:</span>
<button
onClick={() => switchLocale("es")}
className={`text-sm ${locale === "es" ? "text-white font-bold" : "text-gray-400 hover:text-white"}`}
>
ES
</button>
<span className="text-gray-600">|</span>
<button
onClick={() => switchLocale("en")}
className={`text-sm ${locale === "en" ? "text-white font-bold" : "text-gray-400 hover:text-white"}`}
>
EN
</button>
</div>
);
}

View File

@@ -0,0 +1,39 @@
"use client";
import Link from "next/link";
import { useLocale, useTranslations } from "next-intl";
import { LanguageSwitcher } from "./LanguageSwitcher";
export function Navbar() {
const t = useTranslations("nav");
const locale = useLocale();
const links = [
{ href: `/${locale}`, label: t("home") },
{ href: `/${locale}/catalog`, label: t("catalog") },
{ href: `/${locale}/about`, label: t("about") },
{ href: `/${locale}/donate`, label: t("donate") },
];
return (
<nav className="fixed top-0 left-0 right-0 z-50 bg-black/90 backdrop-blur-sm border-b border-white/10">
<div className="max-w-7xl mx-auto px-4 h-16 flex items-center justify-between">
<Link href={`/${locale}`} className="text-xl font-bold text-white tracking-tight">
Project Afterlife
</Link>
<div className="flex items-center gap-6">
{links.map((link) => (
<Link
key={link.href}
href={link.href}
className="text-sm text-gray-300 hover:text-white transition-colors"
>
{link.label}
</Link>
))}
<LanguageSwitcher />
</div>
</div>
</nav>
);
}

1
package-lock.json generated
View File

@@ -37,6 +37,7 @@
"version": "0.1.0", "version": "0.1.0",
"dependencies": { "dependencies": {
"@afterlife/shared": "*", "@afterlife/shared": "*",
"framer-motion": "^12.34.3",
"next": "^15", "next": "^15",
"next-intl": "^4.8.3", "next-intl": "^4.8.3",
"react": "^19", "react": "^19",