feat(navbar): add modular navbar components and color variables

This commit is contained in:
lila 2026-04-19 17:51:43 +02:00
parent 6dbc16f23d
commit 6c4ef371c1
7 changed files with 154 additions and 48 deletions

View file

@ -0,0 +1,40 @@
import { Link, useNavigate } from "@tanstack/react-router";
import { useSession, signOut } from "../../lib/auth-client";
const NavAuth = () => {
const { data: session } = useSession();
const navigate = useNavigate();
const handleSignOut = () => {
void signOut()
.then(() => void navigate({ to: "/" }))
.catch((err) => console.error("Sign out error:", err));
};
return (
<div className="ml-auto">
{session ? (
<button
onClick={handleSignOut}
className="text-sm text-(--color-text-muted) transition-colors duration-200
hover:text-(--color-primary)"
>
Sign out{" "}
<span className="text-(--color-accent)">{session.user.name}</span>
</button>
) : (
<Link
to="/login"
className="text-sm font-medium px-4 py-1.5 rounded-full
text-white bg-(--color-primary)
hover:bg-(--color-primary-dark)
transition-colors duration-200"
>
Sign in
</Link>
)}
</div>
);
};
export default NavAuth;

View file

@ -0,0 +1,18 @@
import NavAuth from "./NavAuth";
import NavLinks from "./NavLinks";
const Navbar = () => {
return (
<header className="sticky top-0 z-50 w-full bg-(--color-surface) border-b border-(--color-primary-light)">
<div className="max-w-5xl mx-auto px-6 h-14 flex items-center gap-8">
<span className="text-sm font-bold tracking-tight text-(--color-primary)">
lila
</span>
<NavLinks />
<NavAuth />
</div>
</header>
);
};
export default Navbar;

View file

@ -0,0 +1,26 @@
import { Link } from "@tanstack/react-router";
type NavLinkProps = { to: string; children: React.ReactNode };
const NavLink = ({ to, children }: NavLinkProps) => {
return (
<Link
to={to}
className="relative text-sm font-medium text-(--color-text-muted) transition-colors duration-200
hover:text-(--color-primary)
[&.active]:text-(--color-primary)
[&.active]:after:absolute
[&.active]:after:-bottom-1
[&.active]:after:left-0
[&.active]:after:w-full
[&.active]:after:h-0.5
[&.active]:after:bg-(--color-accent)
[&.active]:after:rounded-full
[&.active]:after:content-['']"
>
{children}
</Link>
);
};
export default NavLink;

View file

@ -0,0 +1,21 @@
import NavLink from "./NavLink";
const links = [
{ to: "/", label: "Home" },
{ to: "/play", label: "Play" },
{ to: "/multiplayer", label: "Multiplayer" },
];
const NavLinks = () => {
return (
<nav className="flex items-center gap-6">
{links.map(({ to, label }) => (
<NavLink key={to} to={to}>
{label}
</NavLink>
))}
</nav>
);
};
export default NavLinks;

View file

@ -0,0 +1,17 @@
import { Link } from "@tanstack/react-router";
const NavLogin = () => {
return (
<Link
to="/login"
className="text-sm font-medium px-4 py-1.5 rounded-full
text-white bg-(--color-primary)
hover:bg-(--color-primary-dark)
transition-colors duration-200"
>
Sign in
</Link>
);
};
export default NavLogin;

View file

@ -0,0 +1,26 @@
import { useNavigate } from "@tanstack/react-router";
import { signOut } from "../../lib/auth-client";
type NavLogoutProps = { name: string };
const NavLogout = ({ name }: NavLogoutProps) => {
const navigate = useNavigate();
const handleLogout = () => {
void signOut()
.then(() => void navigate({ to: "/" }))
.catch((err) => console.error("logout error:", err));
};
return (
<button
onClick={handleLogout}
className="text-sm text-(--color-text-muted) transition-colors duration-200
hover:text-(--color-primary)"
>
logout <span className="text-(--color-accent)">{name}</span>
</button>
);
};
export default NavLogout;

View file

@ -1,56 +1,14 @@
import {
createRootRoute,
Link,
Outlet,
useNavigate,
} from "@tanstack/react-router";
import { createRootRoute, Outlet } from "@tanstack/react-router";
import { TanStackRouterDevtools } from "@tanstack/react-router-devtools";
import { useSession, signOut } from "../lib/auth-client";
import Navbar from "../components/navbar/NavBar";
const RootLayout = () => {
const { data: session } = useSession();
const navigate = useNavigate();
return (
<>
<div className="p-2 flex gap-2 items-center">
<Link to="/" className="[&.active]:font-bold">
Home
</Link>
<Link to="/play" className="[&.active]:font-bold">
Play
</Link>
<Link to="/multiplayer" className="[&.active]:font-bold">
Multiplayer
</Link>
<div className="ml-auto">
{session ? (
<button
className="text-sm text-gray-600 hover:text-gray-900"
onClick={() => {
void signOut()
.then(() => {
void navigate({ to: "/" });
})
.catch((err) => {
console.error("Sign out error:", err);
});
}}
>
Sign out ({session.user.name})
</button>
) : (
<Link
to="/login"
className="text-sm text-blue-600 hover:text-blue-800"
>
Sign in
</Link>
)}
</div>
</div>
<hr />
<Navbar />
<main className="max-w-5xl mx-auto px-6 py-8">
<Outlet />
</main>
<TanStackRouterDevtools />
</>
);