init
This commit is contained in:
commit
c19b910c36
80 changed files with 16134 additions and 0 deletions
109
app/components/SiteHeader.tsx
Normal file
109
app/components/SiteHeader.tsx
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
import { BookHeart, BookOpen, CalendarRange, UtensilsCrossed } from "lucide-react";
|
||||
import Link from "next/link";
|
||||
import type { ReactNode } from "react";
|
||||
import { ThemeToggle } from "./ThemeToggle";
|
||||
|
||||
export type ActiveNav = "home" | "recipes" | "caydens-corner" | "plan";
|
||||
|
||||
export function Logo({ small = false, subtitle }: { small?: boolean; subtitle?: ReactNode }) {
|
||||
return (
|
||||
<div className="flex shrink-0 items-center gap-2.5">
|
||||
<Link
|
||||
href="/"
|
||||
aria-label="Plan my Meals home"
|
||||
className={`grid shrink-0 place-items-center rounded-lg border border-brand-border bg-brand-950 text-brand-300 transition-colors hover:bg-selected ${
|
||||
small ? "size-7" : "size-9"
|
||||
}`}
|
||||
>
|
||||
<UtensilsCrossed className={small ? "size-3.5" : "size-4"} strokeWidth={2} aria-hidden />
|
||||
</Link>
|
||||
<div className="min-w-0">
|
||||
<Link
|
||||
href="/"
|
||||
className={`block font-serif leading-tight font-semibold tracking-tight whitespace-nowrap hover:text-brand-300 ${
|
||||
small ? "text-sm text-ink-muted" : "text-lg text-ink"
|
||||
}`}
|
||||
>
|
||||
Plan my Meals
|
||||
</Link>
|
||||
<div className="flex items-center gap-1.5 text-xs leading-tight text-ink-faint whitespace-nowrap">
|
||||
<span>
|
||||
by{" "}
|
||||
<a
|
||||
href="https://caydens.dev"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="font-medium text-ink-muted transition-colors hover:text-brand-300 hover:underline"
|
||||
>
|
||||
Cayden Codes
|
||||
</a>
|
||||
</span>
|
||||
{subtitle && (
|
||||
<>
|
||||
<span aria-hidden>·</span>
|
||||
{subtitle}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
interface SiteHeaderProps {
|
||||
active?: ActiveNav;
|
||||
subtitle?: ReactNode;
|
||||
rightSlot?: ReactNode;
|
||||
}
|
||||
|
||||
export function SiteHeader({ active = "home", subtitle, rightSlot }: SiteHeaderProps) {
|
||||
const linkClass = (isCurrent: boolean) =>
|
||||
`trim-cap inline-flex min-h-10 items-center gap-1.5 rounded-lg px-2.5 py-2 text-sm font-medium transition-colors sm:px-3 ${
|
||||
isCurrent ? "bg-selected text-ink" : "text-ink-muted hover:bg-raised hover:text-ink"
|
||||
}`;
|
||||
|
||||
return (
|
||||
<header className="sticky top-0 z-30 border-b border-line bg-surface/90 backdrop-blur-md">
|
||||
<div className="mx-auto flex max-w-7xl items-center gap-2 px-4 py-2.5 sm:gap-4 sm:px-6">
|
||||
<Logo subtitle={subtitle} />
|
||||
|
||||
<nav aria-label="Primary" className="ml-auto flex items-center gap-1 whitespace-nowrap">
|
||||
<Link
|
||||
href="/recipes"
|
||||
aria-current={active === "recipes" ? "page" : undefined}
|
||||
className={linkClass(active === "recipes")}
|
||||
title="Recipe library"
|
||||
>
|
||||
<BookOpen className="size-4 shrink-0" strokeWidth={1.75} aria-hidden />
|
||||
<span className="sr-only md:not-sr-only">Recipes</span>
|
||||
</Link>
|
||||
|
||||
<Link
|
||||
href="/caydens-corner"
|
||||
aria-current={active === "caydens-corner" ? "page" : undefined}
|
||||
className={linkClass(active === "caydens-corner")}
|
||||
title="Cayden's Corner"
|
||||
>
|
||||
<BookHeart className="size-4 shrink-0" strokeWidth={1.75} aria-hidden />
|
||||
<span className="sr-only md:not-sr-only">Cayden's Corner</span>
|
||||
</Link>
|
||||
|
||||
{active !== "plan" && (
|
||||
<Link
|
||||
href="/plan"
|
||||
className="trim-cap ml-1 inline-flex min-h-10 items-center gap-1.5 rounded-lg bg-brand-600 px-3 py-2 text-sm font-semibold text-on-accent shadow-2xs transition-colors hover:bg-brand-500 sm:px-4"
|
||||
>
|
||||
<CalendarRange className="size-4 shrink-0" strokeWidth={2} aria-hidden />
|
||||
<span className="sm:hidden">Planner</span>
|
||||
<span className="hidden sm:inline">Open planner</span>
|
||||
</Link>
|
||||
)}
|
||||
</nav>
|
||||
|
||||
{rightSlot}
|
||||
|
||||
<ThemeToggle />
|
||||
</div>
|
||||
</header>
|
||||
);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue