Files
sass-mohfarawati/components/ui/ui-kit-showcase.tsx
T
2026-03-07 22:28:52 +01:00

523 lines
23 KiB
TypeScript

import { Layers3, Type } from "lucide-react";
import { AppCard } from "@/components/ui/app-card";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import {
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from "@/components/ui/card";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { Textarea } from "@/components/ui/textarea";
type UiKitShowcaseProps = {
localeKey: "de" | "en";
};
function UiKitSection({
title,
description,
children,
}: {
title: string;
description: string;
children: React.ReactNode;
}) {
return (
<AppCard>
<CardHeader>
<CardTitle className="text-xl">{title}</CardTitle>
<CardDescription>{description}</CardDescription>
</CardHeader>
<CardContent>{children}</CardContent>
</AppCard>
);
}
export function UiKitShowcase({ localeKey }: UiKitShowcaseProps) {
const copy =
localeKey === "de"
? {
title: "UI Kit",
intro:
"Zentrale Referenz fuer globale Oberflaechen, Steuerelemente und verschachtelte Ebenen.",
cards: "Cards",
buttons: "Buttons",
inputs: "Inputs",
badges: "Badges",
tabs: "Tabs",
surfaces: "Surfaces",
typography: "Typography",
headers: "Headers",
cardsDesc:
"Aussenflaechen, innere Karten und verschachtelte Ebenen mit einheitlicher Hierarchie.",
buttonsDesc:
"Globale Button Varianten und Groessen aus einer zentralen Quelle.",
inputsDesc:
"Gemeinsame Feldzustande mit derselben inneren Radius- und Oberflaechenlogik.",
badgesDesc:
"Kleine Statusmarken mit minimaler, konsistenter Formensprache.",
surfacesDesc:
"Die gesamte Oberflaechenhierarchie basiert auf Level 1 bis 3 und einer inversen Ebene.",
typographyDesc:
"Typografische Grundstufen fuer Seiten, Sektionen und Metainformationen.",
headersDesc:
"Header Muster fuer Seiten und Sektionen innerhalb des Systems.",
tabsDesc:
"Tabs bleiben in einer Route und verwenden dieselbe verschachtelte Steuerlogik.",
outerCard: "Aeussere Card",
surfaceLevel: "Surface Level 1",
innerCard: "Innere Card",
nestedContent: "Verschachtelte Inhalte nutzen den zweiten Radius und eine weichere Oberflaeche.",
nestedSurface: "Verschachtelte Ebene",
nestedSurfaceText: "Mehr Tiefe ohne einen neuen Component Stil zu erfinden.",
interactiveOuterCard: "Interaktive aeussere Card",
hoverText: "Das Hover Verhalten bleibt an dieselbe Oberflaechenebene gebunden.",
inverseOuterCard: "Inverse aeussere Card",
inverseOuterCardText: "Nur verwenden, wenn ein starker Kontrastblock wirklich noetig ist.",
default: "Standard",
secondary: "Sekundaer",
outline: "Outline",
ghost: "Ghost",
destructive: "Destruktiv",
linkButton: "Link Button",
small: "Klein",
large: "Gross",
iconButton: "Icon Button",
disabled: "Deaktiviert",
defaultInput: "Standard Input",
placeholderText: "Platzhaltertext",
filledInput: "Gefuellter Input",
filledValue: "Gefuellter Wert",
disabledInput: "Deaktivierter Input",
disabledState: "Deaktivierter Zustand",
focusPreview: "Focus Vorschau",
focusedLook: "Fokussierte Ansicht",
errorPreview: "Fehler Vorschau",
invalidValue: "Ungueltiger Wert",
textarea: "Textarea",
textareaValue: "Laengerer Feldzustand fuer mehrzeilige Inhalte.",
success: "Erfolg",
warning: "Warnung",
first: "Erste",
second: "Zweite",
third: "Dritte",
firstTabText: "Inhalt des ersten Tabs innerhalb einer Level 1 Oberflaeche.",
secondTabText: "Inhalt des zweiten Tabs mit derselben globalen Hierarchie.",
thirdTabText: "Inhalt des dritten Tabs ohne lokale Sonderstile.",
surfaceOne: "Surface 1",
surfaceOneText: "Aeussere und primaere Container.",
surfaceTwo: "Surface 2",
surfaceTwoText: "Innere und unterstuetzende Panels.",
surfaceThree: "Surface 3",
surfaceThreeText: "Mehr Betonung ohne neue Styling-Zweige.",
inverse: "Inverse",
inverseText: "Reserviert fuer bewusst eingesetzte Kontrastbloecke.",
eyebrow: "Eyebrow",
pageHeading: "Seitenueberschrift",
pageHeadingText: "Begleitender Absatz fuer primaere Seiteneinfuehrungen und Zusammenfassungen.",
sectionHeading: "Abschnittsueberschrift",
sectionHeadingText: "Fuer gruppierte Bereiche innerhalb einer aeusseren Seitenoberflaeche.",
strongSupportingText: "Betonter Begleittext",
pageHeader: "Seitenheader",
outerSurfaceHeader: "Header der aeusseren Oberflaeche",
outerSurfaceHeaderText: "Dieses Muster wird fuer Seitensektionen mit staerkerer Hierarchie genutzt.",
sectionHeader: "Abschnittsheader",
nestedBlockHeading: "Ueberschrift des verschachtelten Blocks",
nestedBlockHeadingText: "Innerhalb einer aeusseren Card verwenden, wenn Inhalte bereits gruppiert sind."
}
: {
title: "UI Kit",
intro:
"Central reference for global surfaces, controls, and nested interface levels.",
cards: "Cards",
buttons: "Buttons",
inputs: "Inputs",
badges: "Badges",
tabs: "Tabs",
surfaces: "Surfaces",
typography: "Typography",
headers: "Headers",
cardsDesc:
"Outer surfaces, inner cards, and nested levels with one consistent hierarchy.",
buttonsDesc:
"Global button variants and sizes from one shared source of truth.",
inputsDesc:
"Shared field states using the same inner radius and surface logic.",
badgesDesc:
"Small status markers with a minimal and consistent shape language.",
surfacesDesc:
"The full surface hierarchy is built on level 1 through 3 and one inverse layer.",
typographyDesc:
"Typography foundations for pages, sections, and supporting copy.",
headersDesc:
"Header patterns for pages and sections inside the system.",
tabsDesc:
"Tabs stay within one route and use the same nested control logic.",
outerCard: "Outer card",
surfaceLevel: "Surface level 1",
innerCard: "Inner card",
nestedContent: "Nested content uses the secondary radius and a softer surface.",
nestedSurface: "Nested surface",
nestedSurfaceText: "Deeper emphasis without inventing a new component style.",
interactiveOuterCard: "Interactive outer card",
hoverText: "Hover behavior stays attached to the same surface level.",
inverseOuterCard: "Inverse outer card",
inverseOuterCardText: "Use only when a strong contrast block is truly needed.",
default: "Default",
secondary: "Secondary",
outline: "Outline",
ghost: "Ghost",
destructive: "Destructive",
linkButton: "Link button",
small: "Small",
large: "Large",
iconButton: "Icon button",
disabled: "Disabled",
defaultInput: "Default input",
placeholderText: "Placeholder text",
filledInput: "Filled input",
filledValue: "Filled value",
disabledInput: "Disabled input",
disabledState: "Disabled state",
focusPreview: "Focus-style preview",
focusedLook: "Focused look",
errorPreview: "Error-style preview",
invalidValue: "Invalid value",
textarea: "Textarea",
textareaValue: "Longer field state for multiline content.",
success: "Success",
warning: "Warning",
first: "First",
second: "Second",
third: "Third",
firstTabText: "First tab content inside a level 1 surface.",
secondTabText: "Second tab content using the same global hierarchy.",
thirdTabText: "Third tab content without local custom styling.",
surfaceOne: "Surface 1",
surfaceOneText: "Outer and primary containers.",
surfaceTwo: "Surface 2",
surfaceTwoText: "Inner and supporting panels.",
surfaceThree: "Surface 3",
surfaceThreeText: "Raised emphasis without new styling branches.",
inverse: "Inverse",
inverseText: "Reserved for deliberate high-contrast blocks.",
eyebrow: "Eyebrow",
pageHeading: "Page heading",
pageHeadingText: "Supporting paragraph text for primary page introductions and summaries.",
sectionHeading: "Section heading",
sectionHeadingText: "Use this for grouped blocks inside an outer page surface.",
strongSupportingText: "Strong supporting text",
pageHeader: "Page header",
outerSurfaceHeader: "Outer surface header",
outerSurfaceHeaderText: "This pattern is used for page-level sections that need stronger hierarchy.",
sectionHeader: "Section header",
nestedBlockHeading: "Nested block heading",
nestedBlockHeadingText: "Use inside an outer card when content is already grouped."
};
return (
<div className="flex flex-col gap-section">
<AppCard level={3}>
<CardContent className="flex flex-col gap-4 p-6 lg:p-10">
<div className="inline-flex w-fit items-center gap-2 rounded-full border border-input bg-background px-3 py-1 text-xs font-semibold uppercase tracking-[0.14em] text-foreground/80">
<Layers3 className="h-3.5 w-3.5 text-brand-secondary" />
{copy.title}
</div>
<div className="space-y-3">
<h1 className="text-3xl font-semibold tracking-tight text-foreground sm:text-5xl">
{copy.title}
</h1>
<p className="max-w-3xl text-base text-muted-foreground sm:text-lg">
{copy.intro}
</p>
</div>
</CardContent>
</AppCard>
<Tabs defaultValue="cards">
<TabsList>
<TabsTrigger value="cards">{copy.cards}</TabsTrigger>
<TabsTrigger value="buttons">{copy.buttons}</TabsTrigger>
<TabsTrigger value="inputs">{copy.inputs}</TabsTrigger>
<TabsTrigger value="badges">{copy.badges}</TabsTrigger>
<TabsTrigger value="tabs">{copy.tabs}</TabsTrigger>
<TabsTrigger value="surfaces">{copy.surfaces}</TabsTrigger>
<TabsTrigger value="typography">{copy.typography}</TabsTrigger>
<TabsTrigger value="headers">{copy.headers}</TabsTrigger>
</TabsList>
<TabsContent value="cards">
<UiKitSection title={copy.cards} description={copy.cardsDesc}>
<div className="grid gap-6">
<AppCard level={1}>
<CardContent className="space-y-4 p-6">
<div>
<p className="text-sm font-medium text-muted-foreground">{copy.outerCard}</p>
<h3 className="mt-1 text-lg font-semibold text-foreground">{copy.surfaceLevel}</h3>
</div>
<AppCard level={2}>
<CardContent className="space-y-3 p-5">
<div>
<p className="text-sm font-medium text-muted-foreground">{copy.innerCard}</p>
<p className="mt-1 text-sm text-muted-foreground">
{copy.nestedContent}
</p>
</div>
<AppCard level={3}>
<CardContent className="space-y-2 p-4">
<p className="text-sm font-medium text-foreground">{copy.nestedSurface}</p>
<p className="text-sm text-muted-foreground">
{copy.nestedSurfaceText}
</p>
</CardContent>
</AppCard>
</CardContent>
</AppCard>
</CardContent>
</AppCard>
<div className="grid gap-4">
<AppCard level={1} interactive>
<CardContent className="p-5">
<p className="text-sm font-medium text-muted-foreground">{copy.interactiveOuterCard}</p>
<p className="mt-2 text-sm text-muted-foreground">
{copy.hoverText}
</p>
</CardContent>
</AppCard>
<AppCard level="inverse">
<CardContent className="p-5">
<p className="text-sm font-medium text-background/80">
{copy.inverseOuterCard}
</p>
<p className="mt-2 text-sm text-background/88">
{copy.inverseOuterCardText}
</p>
</CardContent>
</AppCard>
</div>
</div>
</UiKitSection>
</TabsContent>
<TabsContent value="buttons">
<UiKitSection title={copy.buttons} description={copy.buttonsDesc}>
<div className="grid gap-6">
<AppCard level={2}>
<CardContent className="flex flex-wrap gap-3 p-5">
<Button>{copy.default}</Button>
<Button variant="secondary">{copy.secondary}</Button>
<Button variant="outline">{copy.outline}</Button>
<Button variant="ghost">{copy.ghost}</Button>
<Button variant="destructive">{copy.destructive}</Button>
<Button variant="link">{copy.linkButton}</Button>
</CardContent>
</AppCard>
<AppCard level={2}>
<CardContent className="flex flex-wrap items-center gap-3 p-5">
<Button size="sm">{copy.small}</Button>
<Button>{copy.default}</Button>
<Button size="lg">{copy.large}</Button>
<Button size="icon" aria-label={copy.iconButton}>
<Layers3 className="h-4 w-4" />
</Button>
<Button disabled>{copy.disabled}</Button>
</CardContent>
</AppCard>
</div>
</UiKitSection>
</TabsContent>
<TabsContent value="inputs">
<UiKitSection title={copy.inputs} description={copy.inputsDesc}>
<div className="grid gap-6">
<AppCard level={2}>
<CardContent className="grid gap-4 p-5">
<Label className="grid gap-2">
{copy.defaultInput}
<Input placeholder={copy.placeholderText} />
</Label>
<Label className="grid gap-2">
{copy.filledInput}
<Input defaultValue={copy.filledValue} />
</Label>
<Label className="grid gap-2">
{copy.disabledInput}
<Input disabled defaultValue={copy.disabledState} />
</Label>
</CardContent>
</AppCard>
<AppCard level={2}>
<CardContent className="grid gap-4 p-5">
<Label className="grid gap-2">
{copy.focusPreview}
<Input
defaultValue={copy.focusedLook}
className="ring-2 ring-ring ring-offset-2"
readOnly
/>
</Label>
<Label className="grid gap-2">
{copy.errorPreview}
<Input
defaultValue={copy.invalidValue}
className="border-destructive text-destructive focus-visible:ring-destructive"
readOnly
/>
</Label>
<Label className="grid gap-2">
{copy.textarea}
<Textarea defaultValue={copy.textareaValue} />
</Label>
</CardContent>
</AppCard>
</div>
</UiKitSection>
</TabsContent>
<TabsContent value="badges">
<UiKitSection title={copy.badges} description={copy.badgesDesc}>
<div className="flex flex-wrap gap-3">
<Badge>{copy.default}</Badge>
<Badge variant="secondary">{copy.secondary}</Badge>
<Badge variant="outline">{copy.outline}</Badge>
<Badge variant="success">{copy.success}</Badge>
<Badge variant="warning">{copy.warning}</Badge>
</div>
</UiKitSection>
</TabsContent>
<TabsContent value="tabs">
<UiKitSection title={copy.tabs} description={copy.tabsDesc}>
<AppCard level={2}>
<CardContent className="space-y-4 p-5">
<Tabs defaultValue="first">
<TabsList>
<TabsTrigger value="first">{copy.first}</TabsTrigger>
<TabsTrigger value="second">{copy.second}</TabsTrigger>
<TabsTrigger value="third">{copy.third}</TabsTrigger>
</TabsList>
<TabsContent value="first">
<AppCard level={1}>
<CardContent className="p-4 text-sm text-muted-foreground">
{copy.firstTabText}
</CardContent>
</AppCard>
</TabsContent>
<TabsContent value="second">
<AppCard level={1}>
<CardContent className="p-4 text-sm text-muted-foreground">
{copy.secondTabText}
</CardContent>
</AppCard>
</TabsContent>
<TabsContent value="third">
<AppCard level={1}>
<CardContent className="p-4 text-sm text-muted-foreground">
{copy.thirdTabText}
</CardContent>
</AppCard>
</TabsContent>
</Tabs>
</CardContent>
</AppCard>
</UiKitSection>
</TabsContent>
<TabsContent value="surfaces">
<UiKitSection title={copy.surfaces} description={copy.surfacesDesc}>
<div className="grid gap-4">
<AppCard level={1}>
<CardContent className="p-5">
<p className="font-medium">{copy.surfaceOne}</p>
<p className="mt-2 text-sm text-muted-foreground">{copy.surfaceOneText}</p>
</CardContent>
</AppCard>
<AppCard level={2}>
<CardContent className="p-5">
<p className="font-medium">{copy.surfaceTwo}</p>
<p className="mt-2 text-sm text-muted-foreground">{copy.surfaceTwoText}</p>
</CardContent>
</AppCard>
<AppCard level={3}>
<CardContent className="p-5">
<p className="font-medium">{copy.surfaceThree}</p>
<p className="mt-2 text-sm text-muted-foreground">{copy.surfaceThreeText}</p>
</CardContent>
</AppCard>
<AppCard level="inverse">
<CardContent className="p-5">
<p className="font-medium text-background">{copy.inverse}</p>
<p className="mt-2 text-sm text-background/88">{copy.inverseText}</p>
</CardContent>
</AppCard>
</div>
</UiKitSection>
</TabsContent>
<TabsContent value="typography">
<UiKitSection title={copy.typography} description={copy.typographyDesc}>
<div className="space-y-6">
<div className="space-y-2">
<p className="text-sm font-medium uppercase tracking-[0.14em] text-muted-foreground">
{copy.eyebrow}
</p>
<h1 className="text-4xl font-semibold tracking-tight text-foreground">
{copy.pageHeading}
</h1>
<p className="max-w-2xl text-base text-muted-foreground">
{copy.pageHeadingText}
</p>
</div>
<AppCard level={2}>
<CardContent className="space-y-3 p-5">
<h2 className="text-2xl font-semibold text-foreground">{copy.sectionHeading}</h2>
<p className="text-sm text-muted-foreground">
{copy.sectionHeadingText}
</p>
<p className="text-sm font-medium text-foreground/82">{copy.strongSupportingText}</p>
</CardContent>
</AppCard>
</div>
</UiKitSection>
</TabsContent>
<TabsContent value="headers">
<UiKitSection title={copy.headers} description={copy.headersDesc}>
<div className="grid gap-6">
<AppCard level={3}>
<CardContent className="space-y-3 p-6">
<div className="inline-flex w-fit items-center gap-2 rounded-full border border-input bg-background px-3 py-1 text-xs font-semibold uppercase tracking-[0.14em] text-foreground/80">
<Type className="h-3.5 w-3.5 text-brand-primary" />
{copy.pageHeader}
</div>
<h2 className="text-3xl font-semibold tracking-tight text-foreground">
{copy.outerSurfaceHeader}
</h2>
<p className="text-base text-muted-foreground">
{copy.outerSurfaceHeaderText}
</p>
</CardContent>
</AppCard>
<AppCard level={2}>
<CardContent className="space-y-3 p-5">
<p className="text-sm font-medium text-muted-foreground">{copy.sectionHeader}</p>
<h3 className="text-xl font-semibold text-foreground">{copy.nestedBlockHeading}</h3>
<p className="text-sm text-muted-foreground">
{copy.nestedBlockHeadingText}
</p>
</CardContent>
</AppCard>
</div>
</UiKitSection>
</TabsContent>
</Tabs>
</div>
);
}