first publish
This commit is contained in:
105
src/components/home/About.tsx
Normal file
105
src/components/home/About.tsx
Normal file
@@ -0,0 +1,105 @@
|
||||
import { cn } from "@/lib/utils";
|
||||
import { flags } from "@/lib/site";
|
||||
import { about as aboutDe, type HomeContent } from "@/content/home";
|
||||
import { Section } from "@/components/layout/Section";
|
||||
import { Lines } from "@/components/motion/Lines";
|
||||
import { Reveal } from "@/components/motion/Reveal";
|
||||
import { Rule } from "@/components/motion/Rule";
|
||||
import { Eyebrow } from "@/components/ui/Eyebrow";
|
||||
import { Ledger } from "@/components/ui/Ledger";
|
||||
import { Marginalia } from "@/components/ui/Marginalia";
|
||||
import { Portrait } from "@/components/ui/Portrait";
|
||||
|
||||
export interface AboutProps {
|
||||
/** `getPhotos().portrait` – `null` renders the documented variant B (no photo). */
|
||||
photo: string | null;
|
||||
/** Inhalt der Sektion. Ohne Angabe die deutsche Fassung – die englische reicht sie durch. */
|
||||
content?: HomeContent["about"];
|
||||
}
|
||||
|
||||
/* H2 on ivory: Playfair 400, max 14ch (spec §3.2 / §6.5). */
|
||||
const H2 =
|
||||
"font-display text-[clamp(2.25rem,1.4rem+3.2vw,4.75rem)] font-normal leading-[1.02] tracking-[-0.01em] text-fg [text-wrap:balance] max-w-[14ch]";
|
||||
|
||||
/* Body: Jost 400, 18 px, max 36rem, paragraph gap 1.25em, German hyphenation. */
|
||||
const BODY = "max-w-[36rem] font-sans text-[1.125rem] leading-[1.6] text-fg [hyphens:auto]";
|
||||
|
||||
/**
|
||||
* 04 · Über Anelia (ivory – spec §6.5). First person, a portrait that stays
|
||||
* in view while reading, the Werdegang as a ledger, marginalia with
|
||||
* verifiable facts. No counters, no logos.
|
||||
*
|
||||
* With photo: Portrait cols 3–6 (sticky) · text + ledger cols 7–12 · marginalia cols 10–12.
|
||||
* Without: text cols 3–8 · ledger cols 3–9 · marginalia under the ledger
|
||||
* (no monogram vignette – see below).
|
||||
*/
|
||||
export function About({ photo, content: about = aboutDe }: AboutProps) {
|
||||
const paragraphs = about.paragraphs.map((p, i) =>
|
||||
i === about.paragraphs.length - 1 && flags.showTwins ? `${p} ${about.twins}` : p,
|
||||
);
|
||||
const hasPhoto = Boolean(photo);
|
||||
|
||||
return (
|
||||
<div data-theme="light" className="relative bg-transparent text-fg">
|
||||
<Rule variant="gold" />
|
||||
<Section
|
||||
id={about.id}
|
||||
theme="light"
|
||||
numeral={about.numeral}
|
||||
label={about.eyebrow}
|
||||
className="py-[clamp(4.5rem,10vh,8rem)] md:py-[clamp(7rem,16vh,14rem)]"
|
||||
>
|
||||
{hasPhoto && (
|
||||
<div className="col-span-12 mb-14 lg:col-span-4 lg:col-start-3 lg:mb-0">
|
||||
<Portrait
|
||||
src={photo}
|
||||
alt={about.alt}
|
||||
aspect="4/5"
|
||||
caption={about.caption}
|
||||
sticky
|
||||
parallax
|
||||
sizes="(min-width: 1024px) 30vw, 100vw"
|
||||
className="w-full max-w-[48svh] lg:max-w-none"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className={cn("col-span-12 lg:row-start-1", hasPhoto ? "lg:col-span-6 lg:col-start-7" : "lg:col-span-6 lg:col-start-3")}>
|
||||
<Eyebrow className="mb-8">{about.eyebrow}</Eyebrow>
|
||||
<Lines as="h2" className={H2}>
|
||||
{about.h2.before}
|
||||
{about.h2.em && <em className="italic">{about.h2.em}</em>}
|
||||
{about.h2.after}
|
||||
</Lines>
|
||||
<div className="mt-10 flex flex-col gap-[1.25em]">
|
||||
{paragraphs.map((text, i) => (
|
||||
<Reveal key={i} as="p" delay={i * 0.08} className={BODY}>
|
||||
{text}
|
||||
</Reveal>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Werdegang ledger: cols 7–12 beside the photo, cols 3–9 without. */}
|
||||
<div className={cn("col-span-12 mt-12 lg:row-start-2 lg:mt-16", hasPhoto ? "lg:col-span-6 lg:col-start-7" : "lg:col-span-7 lg:col-start-3")}>
|
||||
<Ledger variant="werdegang" rows={about.werdegang} stagger={0.08} />
|
||||
</div>
|
||||
|
||||
{/* No monogram vignette in variant B: the WOLF-Prinzip closer directly
|
||||
above already ends on a full-height mark, and section 04 now carries
|
||||
the sticky Bodoni numeral it was missing – a third W in the same
|
||||
viewport turned the signature into wallpaper. */}
|
||||
<Reveal
|
||||
className={cn(
|
||||
"col-span-12 mt-12",
|
||||
hasPhoto ? "lg:col-span-3 lg:col-start-10 lg:row-start-2" : "lg:col-span-7 lg:col-start-3 lg:row-start-3",
|
||||
)}
|
||||
>
|
||||
<Marginalia items={about.marginalia} />
|
||||
</Reveal>
|
||||
</Section>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default About;
|
||||
Reference in New Issue
Block a user