486555dbf2
- Shared SubpageShell (HeaderClient paper strip + ink footer) and SubpageIntro, btn/ghost/card helpers in app/_ui/subpage.tsx - Projects list: poster cards with hard ink shadows, filter pills, ink search field; no fake 800ms skeleton and no framer-motion opacity:0 in SSR - Project detail: poster hero, .plakat-prose markdown, links/stack aside, back link works without JS - Books: server-side fetch (visible without JS), cover + rating pills - Legal notice / privacy: moved to app/_ui/*Client.tsx, root routes removed (middleware always redirects to /[locale]), consent reset via useConsent - ProjectThumbnail rebuilt on Plakat tokens - Old Header.tsx + test removed; brown/cream/sand palettes and unused glass-panel/admin-glass(-light)/liquid-bg-blob/float CSS dropped (liquid palette, glass-card, admin-glass-card stay for admin + 404) - .plakat-prose replaces the missing typography plugin Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
49 lines
2.1 KiB
TypeScript
49 lines
2.1 KiB
TypeScript
import type { ReactNode } from "react";
|
|
|
|
// Gemeinsame Bausteine der Unterseiten im Plakat-Stil. Bewusst ohne "use client",
|
|
// damit Server- und Client-Seiten sie gleichermaßen nutzen können.
|
|
|
|
export const btn =
|
|
"inline-flex items-center gap-2 rounded-full bg-ink px-5 py-3 text-[15px] font-semibold text-paper transition-transform duration-150 ease-out active:scale-[0.97]";
|
|
|
|
export const ghost =
|
|
"inline-flex items-center gap-2 rounded-full px-4 py-2 text-sm font-medium shadow-[inset_0_0_0_1.5px_rgb(var(--plakat-ink))] transition-[background-color,color,transform] duration-150 ease-out hover:bg-ink hover:text-paper active:scale-[0.97]";
|
|
|
|
/** Rahmen mit hartem Versatzschatten, ohne Hintergrund (für farbige Karten) */
|
|
export const frame = "rounded-[18px] border-2 border-ink shadow-[6px_6px_0_rgb(var(--plakat-ink))]";
|
|
|
|
export const card = `${frame} bg-paper`;
|
|
|
|
export const monoLabel = "font-mono text-[13px] leading-snug";
|
|
|
|
interface SubpageIntroProps {
|
|
/** Zurück-Link oben links */
|
|
back: ReactNode;
|
|
/** Kleine Zeile oben rechts, z. B. Kategorie oder Rechtsgrundlage */
|
|
kicker?: ReactNode;
|
|
title: ReactNode;
|
|
children?: ReactNode;
|
|
}
|
|
|
|
/** Kopf einer Unterseite: Zurück-Pille, große Plakat-Zeile, Einleitung. */
|
|
export function SubpageIntro({ back, kicker, title, children }: SubpageIntroProps) {
|
|
return (
|
|
<header className="border-b-2 border-ink pb-8 md:pb-12">
|
|
<div className="flex flex-wrap items-center justify-between gap-3">
|
|
{back}
|
|
{kicker && <p className={monoLabel}>{kicker}</p>}
|
|
</div>
|
|
<h1 className="mt-8 hyphens-auto break-words text-balance font-display text-[clamp(3rem,11vw,9.5rem)] font-extrabold leading-[0.86] tracking-[-0.05em] [font-variation-settings:'wdth'_80] md:mt-12">
|
|
{title}
|
|
<span className="text-signal">.</span>
|
|
</h1>
|
|
{children && <div className="mt-6 max-w-[52ch] text-lg leading-relaxed md:text-xl">{children}</div>}
|
|
</header>
|
|
);
|
|
}
|
|
|
|
/** Pfeil nach links für Zurück-Links, rein dekorativ */
|
|
export function BackArrow() {
|
|
return <span aria-hidden="true">←</span>;
|
|
}
|