Bildmarke als Inline-SVG und Wortmarke, dazu Karte, Button, Badge, Statuspunkt, Tabelle, Kennzahl, Diff-Box, Breadcrumb, Seitenkopf, Leerzustand und MonoKopieren. Die Bausteine kapseln die Designregeln (44 px Klickflaeche, Status nie nur ueber Farbe, Tabellen scrollen im eigenen Container), damit spaetere Seiten sie nicht neu erfinden. Nur MonoKopieren ist Client-Komponente, weil sie die Zwischenablage braucht. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
39 lines
1.3 KiB
TypeScript
39 lines
1.3 KiB
TypeScript
import { ChevronRight } from "lucide-react";
|
|
import Link from "next/link";
|
|
import { Fragment } from "react";
|
|
|
|
export type BreadcrumbEintrag = { titel: string; href?: string };
|
|
|
|
/** Brotkrumen-Navigation; der letzte Eintrag ist die aktuelle Seite (#002). */
|
|
export function Breadcrumb({ pfad }: { pfad: BreadcrumbEintrag[] }) {
|
|
return (
|
|
<nav aria-label="Brotkrumen" className="text-muted text-[13.5px]">
|
|
<ol className="flex flex-wrap items-center gap-x-1 gap-y-1">
|
|
{pfad.map((e, i) => {
|
|
const letzter = i === pfad.length - 1;
|
|
return (
|
|
<Fragment key={i}>
|
|
<li className="min-w-0">
|
|
{e.href && !letzter ? (
|
|
<Link href={e.href} className="hover:text-text rounded transition-colors">
|
|
{e.titel}
|
|
</Link>
|
|
) : (
|
|
<span aria-current={letzter ? "page" : undefined} className={letzter ? "text-text" : ""}>
|
|
{e.titel}
|
|
</span>
|
|
)}
|
|
</li>
|
|
{!letzter && (
|
|
<li aria-hidden className="flex">
|
|
<ChevronRight className="size-3.5" />
|
|
</li>
|
|
)}
|
|
</Fragment>
|
|
);
|
|
})}
|
|
</ol>
|
|
</nav>
|
|
);
|
|
}
|