feat: Implement foundational UI components (Button, Card) and layout components (Section, Container), updating design tokens, styling, and documentation.

This commit is contained in:
1elle1
2026-02-01 14:13:39 +01:00
parent f7ac3d6a99
commit 643231b7b0
12 changed files with 357 additions and 55 deletions

56
.gitignore vendored
View File

@@ -1,42 +1,30 @@
# Dependencies
node_modules/
.pnp/
# dependencies
node_modules
/node_modules
/.pnp
.pnp.js
# Build
.next/
out/
build/
dist/
# testing
/coverage
# Environment
.env
.env.local
.env.development.local
.env.test.local
.env.production.local
# next.js
/.next/
/out/
# Debug
# production
/build
# misc
.DS_Store
*.pem
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
ts-debug.log*
# IDE
.idea/
.vscode/
*.swp
*.swo
.DS_Store
# local env files
.env*.local
# TypeScript
*.tsbuildinfo
next-env.d.ts
# Testing
coverage/
# Misc
*.log
*.pid
*.seed
*.pid.lock
# vercel
.vercel

View File

@@ -48,7 +48,10 @@ Es ist ein neutraler, stabiler Arbeitscontainer, mit dem KI individuelle Website
```
/
├── app/ # Next.js App Router
├── src/ # Source Code (Komponenten, Utils)
├── components/ # Fundament-Komponenten
│ ├── layout/ # Container, Section
│ └── ui/ # Button, Card
├── src/ # Projekt-spezifischer Code (Utils, Hooks)
├── skills/ # KI-Regeln und Guidelines
├── spec/ # Projektspezifikation & Design Tokens
├── theme/ # CSS Variables & Stylesheets
@@ -121,6 +124,14 @@ docker run -p 3000:3000 website
---
## Entwicklungshinweise
> **Build und Dev dürfen nicht gleichzeitig laufen.**
> Next.js kann CSS-Referenzen verlieren, wenn `npm run build` und `npm run dev` parallel ausgeführt werden.
> Nutze `npm run clean` um den `.next` Cache zu löschen, falls Styling-Probleme auftreten.
---
## Wichtig
- Dieses Skeleton erzwingt **kein Design**

56
READ_FIRST.md Normal file
View File

@@ -0,0 +1,56 @@
# READ FIRST
## Pflicht-Lesereihenfolge
Bevor an diesem Projekt gearbeitet wird, müssen folgende Dateien gelesen und verstanden werden:
1. `skills/SYSTEM_SKILLS.md` Grundregeln und Verbote
2. `skills/UI_GUIDELINES.md` Qualitätsstandards für UI
3. `skills/DEFINITION_OF_DONE.md` Abnahmekriterien
4. `spec/ProjectSpec.json` Projektspezifikation
5. `spec/design_tokens.json` Design-Token-Definitionen
6. `prompts/master_prompt.md` Workflow-Anleitung
---
## Entwicklungswarnung
> **Build und Dev dürfen NICHT gleichzeitig laufen.**
>
> Wenn `npm run build` und `npm run dev` parallel ausgeführt werden, verliert Next.js CSS-Referenzen.
> Das führt zu fehlendem Styling und instabilem Hot-Reload.
>
> **Lösung bei Problemen:**
> ```bash
> npm run clean
> ```
> Dieser Befehl löscht den `.next` Cache und stellt einen sauberen Zustand her.
---
## Inline-Styling ist verboten
`style={{ ... }}` ist im gesamten Projekt verboten. Alle Styles müssen über:
- `theme/globals.css` CSS Variables (`:root`)
- `theme/stylesheet.css` Typografie & strukturelle Regeln
- `spec/design_tokens.json` Token-Definitionen
gesteuert werden.
---
## Architektur-Überblick
```
components/
├── layout/
│ ├── Container.tsx → Max-Width, horizontales Padding, responsive
│ └── Section.tsx → Vertikaler Rhythmus (Spacing)
└── ui/
├── Button.tsx → Varianten: primary / secondary / ghost
└── Card.tsx → Neutraler Wrapper (Radius, Border, Shadow)
```
Diese Komponenten verwenden ausschließlich CSS Variables aus `globals.css`.
Sie diktieren KEIN Design sie erzwingen Struktur.

View File

@@ -1,7 +1,14 @@
import { Container } from "@/components/layout/Container";
import { Section } from "@/components/layout/Section";
export default function Page() {
return (
<main>
<p>Ready</p>
<Section>
<Container>
<p>Ready</p>
</Container>
</Section>
</main>
);
}

View File

@@ -0,0 +1,21 @@
import type { ElementType, ReactNode } from "react";
interface ContainerProps {
children: ReactNode;
className?: string;
as?: ElementType;
}
export function Container({
children,
className = "",
as: Tag = "div",
}: ContainerProps) {
return (
<Tag
className={`mx-auto w-full max-w-[var(--container-max-width)] px-[var(--container-padding-x)] ${className}`.trim()}
>
{children}
</Tag>
);
}

View File

@@ -0,0 +1,21 @@
import type { ElementType, ReactNode } from "react";
interface SectionProps {
children: ReactNode;
className?: string;
as?: ElementType;
}
export function Section({
children,
className = "",
as: Tag = "section",
}: SectionProps) {
return (
<Tag
className={`py-[var(--section-spacing-y)] ${className}`.trim()}
>
{children}
</Tag>
);
}

45
components/ui/Button.tsx Normal file
View File

@@ -0,0 +1,45 @@
import type { ButtonHTMLAttributes, ReactNode } from "react";
type ButtonVariant = "primary" | "secondary" | "ghost";
type ButtonSize = "sm" | "md" | "lg";
interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
children: ReactNode;
variant?: ButtonVariant;
size?: ButtonSize;
}
const baseClasses =
"inline-flex items-center justify-center font-medium rounded-[var(--radius-md)] transition-all duration-[var(--duration-normal)] ease-[var(--easing-default)] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[color:var(--color-primary)] disabled:pointer-events-none disabled:opacity-50";
const variantClasses: Record<ButtonVariant, string> = {
primary:
"bg-[var(--color-primary)] text-[color:var(--color-background)] hover:opacity-90",
secondary:
"bg-[var(--color-muted)] text-[color:var(--color-foreground)] border border-[color:var(--color-border)] hover:opacity-80",
ghost:
"bg-transparent text-[color:var(--color-foreground)] hover:bg-[var(--color-muted)]",
};
const sizeClasses: Record<ButtonSize, string> = {
sm: "px-[var(--spacing-sm)] py-[var(--spacing-xs)] text-[length:var(--font-size-sm)]",
md: "px-[var(--spacing-md)] py-[var(--spacing-sm)] text-[length:var(--font-size-base)]",
lg: "px-[var(--spacing-lg)] py-[var(--spacing-md)] text-[length:var(--font-size-lg)]",
};
export function Button({
children,
variant = "primary",
size = "md",
className = "",
...props
}: ButtonProps) {
return (
<button
className={`${baseClasses} ${variantClasses[variant]} ${sizeClasses[size]} ${className}`.trim()}
{...props}
>
{children}
</button>
);
}

21
components/ui/Card.tsx Normal file
View File

@@ -0,0 +1,21 @@
import type { ElementType, ReactNode } from "react";
interface CardProps {
children: ReactNode;
className?: string;
as?: ElementType;
}
export function Card({
children,
className = "",
as: Tag = "div",
}: CardProps) {
return (
<Tag
className={`rounded-[var(--radius-md)] border border-[color:var(--color-border)] shadow-[var(--shadow-sm)] p-[var(--spacing-lg)] ${className}`.trim()}
>
{children}
</Tag>
);
}

View File

@@ -7,7 +7,8 @@
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint"
"lint": "next lint",
"clean": "rm -rf .next"
},
"dependencies": {
"next": "^15.1.0",

View File

@@ -91,5 +91,15 @@
"modal": 400,
"popover": 500,
"tooltip": 600
},
"letterSpacing": {
"tight": "-0.01em",
"normal": "0em",
"wide": "0.05em"
},
"layout": {
"containerMaxWidth": "80rem",
"containerPaddingX": "clamp(1rem, 5vw, 2rem)",
"sectionSpacingY": "4rem"
}
}

View File

@@ -43,6 +43,11 @@
--line-height-normal: 1.5;
--line-height-relaxed: 1.75;
/* Letter Spacing - Placeholders */
--letter-spacing-tight: -0.01em;
--letter-spacing-normal: 0em;
--letter-spacing-wide: 0.05em;
/* Spacing - Placeholders */
--spacing-xs: 0.25rem;
--spacing-sm: 0.5rem;
@@ -79,6 +84,11 @@
--z-modal: 400;
--z-popover: 500;
--z-tooltip: 600;
/* Layout - Placeholders */
--container-max-width: 80rem;
--container-padding-x: clamp(1rem, 5vw, 2rem);
--section-spacing-y: var(--spacing-3xl);
}
/*

View File

@@ -1,37 +1,148 @@
/*
* Stylesheet
*
* Project-specific styles go here.
* Typography & structural rules only.
* NO component styles. NO layout sections.
* This file is imported by globals.css.
*
* Structure:
* 1. Component Styles
* 2. Layout Styles
* 3. Page-specific Styles
* 4. Utility Classes
* 5. Animations
* 1. Typography
* 2. Structural Rules
* 3. Utility Classes
* 4. Animations
*/
/* ==========================================================================
1. Component Styles
1. Typography
========================================================================== */
/* Components are added per project */
h1,
h2,
h3,
h4,
h5,
h6 {
font-weight: var(--font-weight-bold);
line-height: var(--line-height-tight);
letter-spacing: var(--letter-spacing-tight);
margin-top: 0;
margin-bottom: var(--spacing-md);
}
h1 {
font-size: var(--font-size-4xl);
}
h2 {
font-size: var(--font-size-3xl);
}
h3 {
font-size: var(--font-size-2xl);
}
h4 {
font-size: var(--font-size-xl);
}
h5 {
font-size: var(--font-size-lg);
}
h6 {
font-size: var(--font-size-base);
font-weight: var(--font-weight-semibold);
}
p {
margin-top: 0;
margin-bottom: var(--spacing-md);
line-height: var(--line-height-normal);
}
small {
font-size: var(--font-size-sm);
}
strong,
b {
font-weight: var(--font-weight-bold);
}
/* Prevent orphans and widows in text blocks */
p,
li,
dd {
orphans: 2;
widows: 2;
}
/* Lists */
ul,
ol {
margin-top: 0;
margin-bottom: var(--spacing-md);
padding-left: var(--spacing-lg);
}
li {
margin-bottom: var(--spacing-xs);
}
/* Blockquote */
blockquote {
margin: 0 0 var(--spacing-md);
padding-left: var(--spacing-lg);
border-left: 3px solid var(--color-border);
font-style: italic;
}
/* Code */
code {
font-family: var(--font-mono);
font-size: var(--font-size-sm);
}
pre {
margin-top: 0;
margin-bottom: var(--spacing-md);
overflow-x: auto;
}
pre code {
font-size: var(--font-size-sm);
}
/* ==========================================================================
2. Layout Styles
2. Structural Rules
========================================================================== */
/* Layout styles are added per project */
/* Focus styles for keyboard navigation */
:focus-visible {
outline: 2px solid var(--color-primary);
outline-offset: 2px;
}
/* Selection */
::selection {
background-color: var(--color-primary);
color: var(--color-background);
}
/* Reduced motion */
@media (prefers-reduced-motion: reduce) {
*,
*::before,
*::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
scroll-behavior: auto !important;
}
}
/* ==========================================================================
3. Page-specific Styles
========================================================================== */
/* Page styles are added per project */
/* ==========================================================================
4. Utility Classes
3. Utility Classes
========================================================================== */
.visually-hidden {
@@ -47,7 +158,7 @@
}
/* ==========================================================================
5. Animations
4. Animations
========================================================================== */
/* Animations are added per project */