import { cn } from "@/lib/utils";
/**
* UI-Basisbausteine (Craftvia-CD): PageHead (Crumb/Titel/Sub + Aktionen), KPI-Kapsel,
* Tag-Chip, Owner-Chip, Status-Pille. Farbe nie als einziges Statussignal — Pillen
* tragen immer Text.
*/
export function PageHead({
crumb,
title,
sub,
actions,
}: {
crumb: string;
title: string;
sub?: string;
actions?: React.ReactNode;
}) {
return (
{crumb}
{title}
{sub &&
{sub}
}
{actions &&
{actions}
}
);
}
export function KpiCard({
label,
value,
trend,
trendColor = "muted",
}: {
label: string;
value: React.ReactNode;
trend?: string;
trendColor?: "muted" | "risk" | "warn" | "ok";
}) {
const trendColors = {
muted: "text-muted-foreground",
risk: "text-[var(--risk)]",
warn: "text-[var(--warn)]",
ok: "text-[var(--ok)]",
};
return (
{label}
{value}
{trend &&
{trend}
}
);
}
export function Tag({ children }: { children: React.ReactNode }) {
return (
{children}
);
}
export function OwnerChip({ name, noOwnerLabel }: { name?: string | null; noOwnerLabel: string }) {
if (!name) return {noOwnerLabel};
const initials = name
.split(/\s+/)
.map((p) => p[0])
.slice(0, 2)
.join("")
.toUpperCase();
return (
{initials}
{name}
);
}
// Status-Chips: ~12 % Alpha der Funktionsfarbe auf hellem Grund (Brandbook §11.4).
const PILL_TONES = {
ok: "bg-[rgba(35,132,93,0.12)] text-[var(--ok)]",
warn: "bg-[rgba(200,121,18,0.12)] text-[var(--warn)]",
orange: "bg-[rgba(255,106,0,0.12)] text-[#b34a00]",
risk: "bg-[rgba(198,66,66,0.12)] text-[var(--risk)]",
info: "bg-[rgba(47,111,163,0.12)] text-[var(--info)]",
mut: "bg-[rgba(102,114,125,0.12)] text-muted-foreground",
violet: "bg-[rgba(8,46,91,0.1)] text-[var(--primary)]",
} as const;
export function Pill({
tone,
children,
}: {
tone: keyof typeof PILL_TONES;
children: React.ReactNode;
}) {
return (
{children}
);
}
export function SectTitle({ title, sub }: { title: string; sub?: string }) {
return (
);
}