Files
anouma/components/PageHeader.tsx
T

67 lines
2.5 KiB
TypeScript

import type { ReactNode } from "react";
import { Breadcrumbs, type Crumb } from "@/components/Breadcrumbs";
import { OrganicBlob } from "@/components/OrganicBlob";
import { JsonLd, breadcrumbJsonLd } from "@/lib/seo/jsonld";
import { getSiteUrl } from "@/lib/seo/config";
type PageHeaderProps = {
eyebrow?: string;
title: string;
lead?: ReactNode;
crumbs?: Crumb[];
/** Varies the header's decorative blob so every interior page doesn't open with the exact same rose-top-right treatment. */
blobTone?: "rose" | "sage" | "cream" | "mauve";
blobPosition?: "top-right" | "top-left";
/** Shorter vertical padding for pages that don't need much ceremony (e.g. Kontakt). */
compact?: boolean;
};
/** Renders the visual breadcrumb trail AND its matching BreadcrumbList JSON-LD from the same `crumbs` - every page that already passes `crumbs` gets structured breadcrumb data for free. */
export async function PageHeader({
eyebrow,
title,
lead,
crumbs,
blobTone = "rose",
blobPosition = "top-right",
compact = false,
}: PageHeaderProps) {
const breadcrumbData = crumbs?.length
? await (async () => {
const siteUrl = await getSiteUrl();
const items = [
{ name: "Startseite", url: siteUrl },
...crumbs.map((crumb) => ({ name: crumb.title, url: crumb.href ? `${siteUrl}${crumb.href}` : undefined })),
];
return breadcrumbJsonLd(items);
})()
: null;
const blobPositionClass = blobPosition === "top-left" ? "-left-20 -top-20" : "-right-20 -top-20";
return (
<section
className={`relative overflow-hidden border-b border-anouma-taupe/10 bg-anouma-cream-light ${
compact ? "pb-10 pt-10 sm:pb-12 sm:pt-12" : "pb-16 pt-14 sm:pb-20 sm:pt-20"
}`}
>
<OrganicBlob tone={blobTone} className={`${blobPositionClass} h-72 w-72`} />
<div className="relative mx-auto max-w-6xl px-6 sm:px-8 lg:px-12">
{breadcrumbData && <JsonLd data={breadcrumbData} />}
{crumbs && <Breadcrumbs items={crumbs} />}
{eyebrow && (
<p className="mb-4 text-xs font-medium uppercase tracking-[0.24em] text-anouma-plum">
{eyebrow}
</p>
)}
<h1 className="max-w-3xl text-balance font-serif text-4xl font-medium leading-tight text-anouma-plum sm:text-5xl lg:text-6xl">
{title}
</h1>
{lead && (
<div className="mt-5 max-w-2xl text-lg leading-relaxed text-anouma-plum">{lead}</div>
)}
</div>
</section>
);
}