first publish
This commit is contained in:
commit
b8e41b4d55
147 files changed
+19367
No files matched your search
@@ -0,0 +1,102 @@
|
||||
import { cn } from "@/lib/utils";
|
||||
import { flags } from "@/lib/site";
|
||||
import { isPlaceholder, splitPlaceholders } from "@/lib/legal";
|
||||
import type { FactItem } from "@/content/home";
|
||||
|
||||
export type { FactItem };
|
||||
|
||||
export interface FactsProps {
|
||||
items: readonly FactItem[];
|
||||
/**
|
||||
* `stack` = mono lines with gold ticks (hero, top right).
|
||||
* `table` = two-column label / value table on bone with a hairline frame (Rahmen).
|
||||
*/
|
||||
variant?: "stack" | "table";
|
||||
/** Table heading (DM Mono caps), e.g. „Rahmen“. */
|
||||
title?: string;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders „[…]“ segments in the accent colour (`--gold-deep` on light, `--gold` on dark).
|
||||
*
|
||||
* Deliberately flag-agnostic: cutting a placeholder out of a running sentence leaves
|
||||
* fragments („Auswertungsgespräch .“), so the launch switch is a build guard, not a
|
||||
* strip – `assertNoPlaceholders` in every content module aborts the build while a
|
||||
* placeholder is still open (src/lib/legal.ts, list in CONTENT_TODO).
|
||||
*/
|
||||
export function PlaceholderText({ text }: { text: string }) {
|
||||
return (
|
||||
<>
|
||||
{splitPlaceholders(text).map((seg, i) =>
|
||||
seg.placeholder ? (
|
||||
<span key={i} className="text-accent">
|
||||
{seg.text}
|
||||
</span>
|
||||
) : (
|
||||
<span key={i}>{seg.text}</span>
|
||||
),
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
/** Drops whole placeholder ROWS when `flags.showPlaceholders` is off (inline placeholders
|
||||
inside a value are the build guard's job, not this filter's – see PlaceholderText). */
|
||||
export function visibleFacts(items: readonly FactItem[]): FactItem[] {
|
||||
return items.filter((f) => flags.showPlaceholders || !(f.placeholder || isPlaceholder(f.value)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Facts stack (Format · Sprache · Ort · Dauer): DM Mono 12 px, one gold tick
|
||||
* per line, label muted, value in the foreground colour. Both variants are
|
||||
* ledgers – tick / label / value are columns with one left edge each, not an
|
||||
* inline run that starts the value at a different x on every row.
|
||||
*/
|
||||
export function Facts({ items, variant = "stack", title, className }: FactsProps) {
|
||||
const rows = visibleFacts(items);
|
||||
if (!rows.length) return null;
|
||||
|
||||
if (variant === "table") {
|
||||
return (
|
||||
<div className={cn("border border-line bg-surface p-6 sm:p-10", className)}>
|
||||
{title && <p className="mb-6 font-mono text-xs uppercase tracking-[0.12em] text-accent">{title}</p>}
|
||||
<dl className="font-mono text-xs tracking-[0.06em] tabular-nums">
|
||||
{rows.map((f) => (
|
||||
/* Below sm the value column would be ~150 px inside the padded box and long
|
||||
values („Inhouse-Workshop 1–2 Tage / Trainingsreihe / Online“) break over four
|
||||
lines – so the label sits above the value there, identically on every page. */
|
||||
<div key={f.label} className="grid grid-cols-1 gap-x-6 gap-y-1 border-b border-line py-3 last:border-b-0 sm:grid-cols-[1fr_3fr]">
|
||||
<dt className="text-fg-muted">{f.label}</dt>
|
||||
<dd className="text-fg">
|
||||
<PlaceholderText text={f.value} />
|
||||
</dd>
|
||||
</div>
|
||||
))}
|
||||
</dl>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
/* Three rails: tick | label (max-content, so every label ends on one edge) | value. */
|
||||
<dl
|
||||
className={cn(
|
||||
"grid grid-cols-[1.5rem_max-content_1fr] gap-x-3 gap-y-3 font-mono text-xs tracking-[0.06em] tabular-nums",
|
||||
className,
|
||||
)}
|
||||
>
|
||||
{rows.map((f) => (
|
||||
<div key={f.label} className="contents">
|
||||
<span aria-hidden="true" className="mt-[0.55em] h-px w-6 self-start bg-accent" />
|
||||
<dt className="text-fg-muted">{f.label}</dt>
|
||||
<dd className="text-fg">
|
||||
<PlaceholderText text={f.value} />
|
||||
</dd>
|
||||
</div>
|
||||
))}
|
||||
</dl>
|
||||
);
|
||||
}
|
||||
|
||||
export default Facts;
|
||||
Reference in new issue
Block a user