deadhead-space-freight-tycoon/apps/web/src/layout/Layout.tsx

49 lines
1.7 KiB
TypeScript

import type { ReactNode } from "react";
import { NavLink, Outlet } from "react-router";
import { SCREENS } from "../routes";
export interface LayoutProps {
/** Shown at the top right; live values arrive with the player state and clock steps. */
credits?: ReactNode;
clock?: ReactNode;
}
/** Header with credits and game clock, the current screen, and a bottom tab bar. */
export function Layout({ credits = "—", clock = "—" }: LayoutProps) {
return (
<div className="flex min-h-dvh flex-col bg-slate-950 text-slate-100">
<header className="sticky top-0 z-10 flex items-center justify-between gap-2 border-b border-slate-800 bg-slate-950/95 px-4 py-2">
<span className="truncate text-sm font-bold tracking-wide">DEADHEAD</span>
<div className="flex shrink-0 items-center gap-3 text-sm tabular-nums">
<span aria-label="Credits">{credits}</span>
<span aria-label="Game clock" className="text-slate-400">
{clock}
</span>
</div>
</header>
<main className="flex-1 overflow-x-hidden pb-20">
<Outlet />
</main>
<nav
aria-label="Main"
className="fixed inset-x-0 bottom-0 grid grid-cols-6 border-t border-slate-800 bg-slate-950 pb-[env(safe-area-inset-bottom)]"
>
{SCREENS.map((screen) => (
<NavLink
key={screen.path}
to={screen.path}
end={screen.path === "/"}
className={({ isActive }) =>
`truncate px-1 py-3 text-center text-xs ${isActive ? "font-semibold text-amber-400" : "text-slate-400"}`
}
>
{screen.label}
</NavLink>
))}
</nav>
</div>
);
}