feat: Implement foundational UI components (Button, Card) and layout components (Section, Container), updating design tokens, styling, and documentation.
This commit is contained in:
56
.gitignore
vendored
56
.gitignore
vendored
@@ -1,42 +1,30 @@
|
|||||||
# Dependencies
|
# dependencies
|
||||||
node_modules/
|
node_modules
|
||||||
.pnp/
|
/node_modules
|
||||||
|
/.pnp
|
||||||
.pnp.js
|
.pnp.js
|
||||||
|
|
||||||
# Build
|
# testing
|
||||||
.next/
|
/coverage
|
||||||
out/
|
|
||||||
build/
|
|
||||||
dist/
|
|
||||||
|
|
||||||
# Environment
|
# next.js
|
||||||
.env
|
/.next/
|
||||||
.env.local
|
/out/
|
||||||
.env.development.local
|
|
||||||
.env.test.local
|
|
||||||
.env.production.local
|
|
||||||
|
|
||||||
# Debug
|
# production
|
||||||
|
/build
|
||||||
|
|
||||||
|
# misc
|
||||||
|
.DS_Store
|
||||||
|
*.pem
|
||||||
|
|
||||||
|
# debug
|
||||||
npm-debug.log*
|
npm-debug.log*
|
||||||
yarn-debug.log*
|
yarn-debug.log*
|
||||||
yarn-error.log*
|
ts-debug.log*
|
||||||
|
|
||||||
# IDE
|
# local env files
|
||||||
.idea/
|
.env*.local
|
||||||
.vscode/
|
|
||||||
*.swp
|
|
||||||
*.swo
|
|
||||||
.DS_Store
|
|
||||||
|
|
||||||
# TypeScript
|
# vercel
|
||||||
*.tsbuildinfo
|
.vercel
|
||||||
next-env.d.ts
|
|
||||||
|
|
||||||
# Testing
|
|
||||||
coverage/
|
|
||||||
|
|
||||||
# Misc
|
|
||||||
*.log
|
|
||||||
*.pid
|
|
||||||
*.seed
|
|
||||||
*.pid.lock
|
|
||||||
|
|||||||
13
README.md
13
README.md
@@ -48,7 +48,10 @@ Es ist ein neutraler, stabiler Arbeitscontainer, mit dem KI individuelle Website
|
|||||||
```
|
```
|
||||||
/
|
/
|
||||||
├── app/ # Next.js App Router
|
├── 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
|
├── skills/ # KI-Regeln und Guidelines
|
||||||
├── spec/ # Projektspezifikation & Design Tokens
|
├── spec/ # Projektspezifikation & Design Tokens
|
||||||
├── theme/ # CSS Variables & Stylesheets
|
├── 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
|
## Wichtig
|
||||||
|
|
||||||
- Dieses Skeleton erzwingt **kein Design**
|
- Dieses Skeleton erzwingt **kein Design**
|
||||||
|
|||||||
56
READ_FIRST.md
Normal file
56
READ_FIRST.md
Normal 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.
|
||||||
@@ -1,7 +1,14 @@
|
|||||||
|
import { Container } from "@/components/layout/Container";
|
||||||
|
import { Section } from "@/components/layout/Section";
|
||||||
|
|
||||||
export default function Page() {
|
export default function Page() {
|
||||||
return (
|
return (
|
||||||
<main>
|
<main>
|
||||||
|
<Section>
|
||||||
|
<Container>
|
||||||
<p>Ready</p>
|
<p>Ready</p>
|
||||||
|
</Container>
|
||||||
|
</Section>
|
||||||
</main>
|
</main>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
21
components/layout/Container.tsx
Normal file
21
components/layout/Container.tsx
Normal 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>
|
||||||
|
);
|
||||||
|
}
|
||||||
21
components/layout/Section.tsx
Normal file
21
components/layout/Section.tsx
Normal 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
45
components/ui/Button.tsx
Normal 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
21
components/ui/Card.tsx
Normal 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>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -7,7 +7,8 @@
|
|||||||
"dev": "next dev",
|
"dev": "next dev",
|
||||||
"build": "next build",
|
"build": "next build",
|
||||||
"start": "next start",
|
"start": "next start",
|
||||||
"lint": "next lint"
|
"lint": "next lint",
|
||||||
|
"clean": "rm -rf .next"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"next": "^15.1.0",
|
"next": "^15.1.0",
|
||||||
|
|||||||
@@ -91,5 +91,15 @@
|
|||||||
"modal": 400,
|
"modal": 400,
|
||||||
"popover": 500,
|
"popover": 500,
|
||||||
"tooltip": 600
|
"tooltip": 600
|
||||||
|
},
|
||||||
|
"letterSpacing": {
|
||||||
|
"tight": "-0.01em",
|
||||||
|
"normal": "0em",
|
||||||
|
"wide": "0.05em"
|
||||||
|
},
|
||||||
|
"layout": {
|
||||||
|
"containerMaxWidth": "80rem",
|
||||||
|
"containerPaddingX": "clamp(1rem, 5vw, 2rem)",
|
||||||
|
"sectionSpacingY": "4rem"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,6 +43,11 @@
|
|||||||
--line-height-normal: 1.5;
|
--line-height-normal: 1.5;
|
||||||
--line-height-relaxed: 1.75;
|
--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 - Placeholders */
|
||||||
--spacing-xs: 0.25rem;
|
--spacing-xs: 0.25rem;
|
||||||
--spacing-sm: 0.5rem;
|
--spacing-sm: 0.5rem;
|
||||||
@@ -79,6 +84,11 @@
|
|||||||
--z-modal: 400;
|
--z-modal: 400;
|
||||||
--z-popover: 500;
|
--z-popover: 500;
|
||||||
--z-tooltip: 600;
|
--z-tooltip: 600;
|
||||||
|
|
||||||
|
/* Layout - Placeholders */
|
||||||
|
--container-max-width: 80rem;
|
||||||
|
--container-padding-x: clamp(1rem, 5vw, 2rem);
|
||||||
|
--section-spacing-y: var(--spacing-3xl);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -1,37 +1,148 @@
|
|||||||
/*
|
/*
|
||||||
* Stylesheet
|
* Stylesheet
|
||||||
*
|
*
|
||||||
* Project-specific styles go here.
|
* Typography & structural rules only.
|
||||||
|
* NO component styles. NO layout sections.
|
||||||
* This file is imported by globals.css.
|
* This file is imported by globals.css.
|
||||||
*
|
*
|
||||||
* Structure:
|
* Structure:
|
||||||
* 1. Component Styles
|
* 1. Typography
|
||||||
* 2. Layout Styles
|
* 2. Structural Rules
|
||||||
* 3. Page-specific Styles
|
* 3. Utility Classes
|
||||||
* 4. Utility Classes
|
* 4. Animations
|
||||||
* 5. 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
|
3. Utility Classes
|
||||||
========================================================================== */
|
|
||||||
|
|
||||||
/* Page styles are added per project */
|
|
||||||
|
|
||||||
/* ==========================================================================
|
|
||||||
4. Utility Classes
|
|
||||||
========================================================================== */
|
========================================================================== */
|
||||||
|
|
||||||
.visually-hidden {
|
.visually-hidden {
|
||||||
@@ -47,7 +158,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* ==========================================================================
|
/* ==========================================================================
|
||||||
5. Animations
|
4. Animations
|
||||||
========================================================================== */
|
========================================================================== */
|
||||||
|
|
||||||
/* Animations are added per project */
|
/* Animations are added per project */
|
||||||
|
|||||||
Reference in New Issue
Block a user