- Update CLAUDE.md to mandate informal "Du" form for user communication in all UI text and emails. - Modify LoginForm and RegisterForm components to reflect informal language in validation messages and placeholders. - Add secure connection indicators in LoginForm for user awareness. - Update alert component styles for better visual feedback. - Introduce experimenta company information document for user reference.
1296 lines
27 KiB
Markdown
1296 lines
27 KiB
Markdown
# experimenta Design System
|
||
|
||
**Version:** 1.0
|
||
**Letzte Aktualisierung:** 2025-10-30
|
||
**Font:** Roboto (Open Source Alternative zu DIN OT)
|
||
|
||
Dieses Design System definiert die visuelle Identität und Komponenten-Bibliothek für **my.experimenta.science**. Es basiert auf dem Corporate Design der experimenta Science Center Website und den bereitgestellten Design-Vorlagen.
|
||
|
||
---
|
||
|
||
## ⚠️ Wichtiger Hinweis zu Schriftarten
|
||
|
||
**Wir verwenden Roboto statt der DIN OT Hausschrift.**
|
||
|
||
**Gründe:**
|
||
- **Open Source:** Roboto ist kostenlos und frei verfügbar
|
||
- **Web-Performance:** Optimiert für digitale Anwendungen
|
||
- **Ähnliche Optik:** Moderne, klare Sans-Serif ähnlich zu DIN OT
|
||
- **DSGVO-konform:** Lokales Hosting ohne externe CDN-Abhängigkeit (Google Fonts)
|
||
|
||
**Font-Hosting:**
|
||
- Die Roboto-Schrift wird lokal aus `/public/fonts/roboto/` geladen
|
||
- @font-face Deklarationen befinden sich in `assets/css/tailwind.css`
|
||
- Benötigte Weights: 300 (Light), 400 (Regular), 500 (Medium), 700 (Bold)
|
||
- Format: WOFF2 (beste Kompression, moderne Browser-Unterstützung)
|
||
|
||
---
|
||
|
||
## Inhaltsverzeichnis
|
||
|
||
1. [Farbpalette](#farbpalette)
|
||
2. [Typografie](#typografie)
|
||
3. [Spacing & Layout](#spacing--layout)
|
||
4. [Komponenten](#komponenten)
|
||
- [Buttons](#1-buttons)
|
||
- [Cards](#2-cards)
|
||
- [Status Messages](#3-status-messages)
|
||
- [Progress Bar](#4-progress-bar)
|
||
- [Forms](#5-forms)
|
||
- [Links](#6-links)
|
||
- [Logo](#7-logo)
|
||
- [Icons](#8-icons)
|
||
5. [Animationen & Transitions](#animationen--transitions)
|
||
6. [Accessibility](#accessibility)
|
||
|
||
---
|
||
|
||
## Farbpalette
|
||
|
||
### Primärfarben
|
||
|
||
**Experimenta Magenta** (Hauptfarbe)
|
||
|
||
```css
|
||
--color-primary: #e6007e;
|
||
--color-primary-hover: #c2006a;
|
||
--color-primary-light: #ff4081;
|
||
```
|
||
|
||
**Verwendung:** Primary Buttons, Links, aktive Zustände, Brand-Elemente
|
||
|
||
**Experimenta Pink**
|
||
|
||
```css
|
||
--color-secondary: #e91e63;
|
||
--color-secondary-dark: #c2185b;
|
||
```
|
||
|
||
**Verwendung:** Secondary Buttons, Footer Headings, Social Media Icons
|
||
|
||
**Experimenta Orange** (Akzent)
|
||
|
||
```css
|
||
--color-accent: #f59d24;
|
||
--color-accent-hover: #ffb347;
|
||
```
|
||
|
||
**Verwendung:** Border-Akzente (links), Hover-Effekte, Highlights, Labels
|
||
|
||
**Experimenta Rot** (Button-Gradient)
|
||
|
||
```css
|
||
--color-red: #e40521;
|
||
```
|
||
|
||
**Verwendung:** Button-Gradienten, Error-Zustände (zusammen mit Magenta)
|
||
|
||
### Background-Farben
|
||
|
||
**Dark Gradient** (Haupt-Background)
|
||
|
||
```css
|
||
--bg-gradient-primary: linear-gradient(135deg, #2e1065 0%, #1a0a3a 50%, #0f051d 100%);
|
||
```
|
||
|
||
**Purple Variants**
|
||
|
||
```css
|
||
--color-purple-dark: #2e1065; /* Start des Gradienten */
|
||
--color-purple-deeper: #1a0a3a; /* Mitte des Gradienten */
|
||
--color-purple-darkest: #0f051d; /* Ende des Gradienten */
|
||
```
|
||
|
||
**Header Background**
|
||
|
||
```css
|
||
--bg-header: rgba(46, 16, 101, 0.95); /* Mit backdrop-filter: blur(10px) */
|
||
```
|
||
|
||
**Footer Background**
|
||
|
||
```css
|
||
--bg-footer: linear-gradient(135deg, #1a0a3a 0%, #0f051d 100%);
|
||
```
|
||
|
||
### Glassmorphism (Cards & Containers)
|
||
|
||
```css
|
||
--glass-background: linear-gradient(135deg, rgba(255, 255, 255, 0.1), rgba(255, 255, 255, 0.05));
|
||
--glass-backdrop: blur(15px);
|
||
--glass-border: 1px solid rgba(255, 255, 255, 0.2);
|
||
--glass-shadow: 0 20px 40px rgba(0, 0, 0, 0.3);
|
||
```
|
||
|
||
**Section Backgrounds (auf Glassmorphism Cards)**
|
||
|
||
```css
|
||
--bg-section: rgba(255, 255, 255, 0.08); /* Leicht heller als Card */
|
||
--bg-section-hover: rgba(255, 255, 255, 0.15);
|
||
```
|
||
|
||
### Semantische Farben
|
||
|
||
**Success**
|
||
|
||
```css
|
||
--color-success: #46c74a;
|
||
--color-success-dark: #3ba83e;
|
||
--color-success-gradient: linear-gradient(90deg, #46c74a 0%, #66d96a 50%, #46c74a 100%);
|
||
```
|
||
|
||
**Error**
|
||
|
||
```css
|
||
--color-error: #e53e3e;
|
||
--color-error-dark: #c53030;
|
||
```
|
||
|
||
**Warning**
|
||
|
||
```css
|
||
--color-warning: #f59d24;
|
||
--color-warning-dark: #dd8a1e;
|
||
```
|
||
|
||
**Info**
|
||
|
||
```css
|
||
--color-info: #4299e1;
|
||
--color-info-dark: #3182ce;
|
||
```
|
||
|
||
### Text-Farben
|
||
|
||
```css
|
||
--text-primary: #ffffff; /* Haupt-Text auf dunklem BG */
|
||
--text-secondary: rgba(255, 255, 255, 0.9); /* Sekundär-Text */
|
||
--text-muted: rgba(255, 255, 255, 0.8); /* Footer, Labels */
|
||
--text-disabled: rgba(255, 255, 255, 0.5); /* Disabled Elemente */
|
||
|
||
/* Text auf hellem Background (falls benötigt) */
|
||
--text-dark: #333333;
|
||
--text-dark-secondary: #666666;
|
||
```
|
||
|
||
### Border-Farben
|
||
|
||
```css
|
||
--border-accent: 4px solid #f59d24; /* Links-Border für Sections */
|
||
--border-light: 1px solid rgba(255, 255, 255, 0.2); /* Card Borders */
|
||
--border-footer: 1px solid rgba(255, 255, 255, 0.1); /* Footer Divider */
|
||
```
|
||
|
||
---
|
||
|
||
## Typografie
|
||
|
||
### Font-Family
|
||
|
||
**Roboto** (Open Source, ähnlich zu DIN OT, lokal gehostet)
|
||
|
||
```css
|
||
font-family: 'Roboto', sans-serif;
|
||
```
|
||
|
||
**Lokales Hosting:**
|
||
|
||
Die Roboto-Schrift wird lokal aus `/public/fonts/roboto/` geladen:
|
||
|
||
```bash
|
||
public/fonts/roboto/
|
||
├── Roboto-VariableFont-latin.woff2 # Variable Font (Weight 100-900)
|
||
└── roboto.css # @font-face Deklarationen
|
||
```
|
||
|
||
**Variable Font:** Wir nutzen eine einzige Variable Font Datei, die alle Weights von 100-900 abdeckt. Das bedeutet bessere Performance (nur eine Datei statt 4 separate Dateien) und nahtlose Übergänge zwischen Font-Weights.
|
||
|
||
**@font-face Deklarationen:** Siehe `assets/css/tailwind.css` (Zeile 15-40)
|
||
|
||
**Download:** Die Datei wurde bereits heruntergeladen. Falls neu benötigt: [Google Fonts - Roboto](https://fonts.google.com/specimen/Roboto) → Download → WOFF2 Format → Variable Font auswählen
|
||
|
||
**Gewichte:**
|
||
|
||
- `300` - Light (Headlines)
|
||
- `400` - Regular (Body Text)
|
||
- `500` - Medium (Buttons, Labels)
|
||
- `700` - Bold (Footer Links, Strong Text)
|
||
|
||
### Font-Scale (Desktop)
|
||
|
||
| Element | Size | Weight | Line Height | Letter Spacing |
|
||
| -------------- | ---- | ------ | ----------- | -------------- |
|
||
| **H1** | 36px | 300 | 1.2 | -1px |
|
||
| **H2** | 30px | 300 | 1.3 | -0.5px |
|
||
| **H3** | 24px | 400 | 1.4 | 0 |
|
||
| **H4** | 20px | 500 | 1.4 | 0 |
|
||
| **H5** | 18px | 500 | 1.5 | 0.5px |
|
||
| **H6** | 16px | 600 | 1.5 | 0.5px |
|
||
| **Body** | 18px | 400 | 1.7 | 0 |
|
||
| **Body Small** | 16px | 400 | 1.6 | 0 |
|
||
| **Caption** | 14px | 400 | 1.6 | 0 |
|
||
| **Tiny** | 12px | 400 | 1.5 | 0 |
|
||
|
||
### Responsive Font-Scale
|
||
|
||
**Tablet (≤768px):**
|
||
|
||
```css
|
||
H1: 28px
|
||
H2: 24px
|
||
H3: 20px
|
||
Body: 16px
|
||
```
|
||
|
||
**Mobile (≤480px):**
|
||
|
||
```css
|
||
H1: 24px
|
||
H2: 20px
|
||
H3: 18px
|
||
Body: 14px
|
||
```
|
||
|
||
### Tailwind Klassen
|
||
|
||
```html
|
||
<!-- Headlines -->
|
||
<h1 class="text-4xl md:text-3xl sm:text-2xl font-light tracking-tight">
|
||
<h2 class="text-3xl md:text-2xl sm:text-xl font-light">
|
||
<h3 class="text-2xl md:text-xl sm:text-lg font-normal">
|
||
<!-- Body Text -->
|
||
<p class="text-lg md:text-base sm:text-sm leading-relaxed">
|
||
<!-- Labels -->
|
||
<span class="text-lg md:text-base sm:text-sm font-medium tracking-wide"></span>
|
||
</p>
|
||
</h3>
|
||
</h2>
|
||
</h1>
|
||
```
|
||
|
||
---
|
||
|
||
## Spacing & Layout
|
||
|
||
### Spacing-System (8px Grid)
|
||
|
||
```css
|
||
--space-1: 4px;
|
||
--space-2: 8px;
|
||
--space-3: 12px;
|
||
--space-4: 16px;
|
||
--space-5: 20px;
|
||
--space-6: 24px;
|
||
--space-8: 30px;
|
||
--space-10: 40px;
|
||
--space-15: 60px;
|
||
--space-20: 80px;
|
||
```
|
||
|
||
### Container Max-Widths
|
||
|
||
```css
|
||
--container-main: 800px; /* Main Content (forms, text) */
|
||
--container-wide: 1200px; /* Footer, wide sections */
|
||
--container-full: 1760px; /* Full-width content (aus Website) */
|
||
```
|
||
|
||
### Border-Radius
|
||
|
||
```css
|
||
--radius-sm: 6px; /* Small elements (badges) */
|
||
--radius-md: 12px; /* Sections, Info-Cards */
|
||
--radius-lg: 15px; /* Standard Cards (mobile) */
|
||
--radius-xl: 20px; /* Standard Cards (desktop) */
|
||
--radius-2xl: 25px; /* Buttons */
|
||
--radius-full: 100%; /* Icons, Avatar */
|
||
```
|
||
|
||
### Breakpoints
|
||
|
||
```css
|
||
/* Mobile First */
|
||
--breakpoint-sm: 480px; /* Small phones */
|
||
--breakpoint-md: 768px; /* Tablets */
|
||
--breakpoint-lg: 1024px; /* Small desktops */
|
||
--breakpoint-xl: 1280px; /* Large desktops */
|
||
```
|
||
|
||
**Verwendung in Tailwind:**
|
||
|
||
```html
|
||
<!-- Mobile First: base = mobile, md = tablet, lg = desktop -->
|
||
<div class="p-4 md:p-8 lg:p-15"></div>
|
||
```
|
||
|
||
### Standard Paddings
|
||
|
||
**Cards:**
|
||
|
||
```css
|
||
/* Desktop */
|
||
padding: 60px 40px;
|
||
|
||
/* Tablet */
|
||
@media (max-width: 768px) {
|
||
padding: 40px 20px;
|
||
}
|
||
|
||
/* Mobile */
|
||
@media (max-width: 480px) {
|
||
padding: 30px 15px;
|
||
}
|
||
```
|
||
|
||
**Sections:**
|
||
|
||
```css
|
||
padding: 30px;
|
||
|
||
/* Tablet */
|
||
@media (max-width: 768px) {
|
||
padding: 25px 20px;
|
||
}
|
||
|
||
/* Mobile */
|
||
@media (max-width: 480px) {
|
||
padding: 20px 15px;
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## Komponenten
|
||
|
||
### 1. Buttons
|
||
|
||
#### Primary Button
|
||
|
||
**Style:**
|
||
|
||
```css
|
||
background: #e6007e;
|
||
background-image: linear-gradient(to left, #e6007e, #e6007e, #e40521, #e6007e);
|
||
background-size: 300%;
|
||
color: #ffffff;
|
||
padding: 10px 30px;
|
||
border-radius: 25px;
|
||
font-size: 18px;
|
||
font-weight: 500;
|
||
transition:
|
||
background-position 1s,
|
||
all 0.3s ease;
|
||
|
||
/* Hover */
|
||
background-position: 100%;
|
||
```
|
||
|
||
**Tailwind:**
|
||
|
||
```html
|
||
<button class="btn-primary">Zur experimenta Startseite</button>
|
||
```
|
||
|
||
**CSS Klasse (Tailwind Config):**
|
||
|
||
```css
|
||
.btn-primary {
|
||
@apply bg-gradient-to-l from-primary via-red to-primary;
|
||
@apply bg-[length:300%] bg-left;
|
||
@apply text-white px-8 py-2.5 rounded-full;
|
||
@apply text-lg font-medium;
|
||
@apply transition-all duration-300;
|
||
@apply hover:bg-right;
|
||
}
|
||
```
|
||
|
||
#### Secondary Button
|
||
|
||
**Style:**
|
||
|
||
```css
|
||
background: transparent;
|
||
border: 2px solid rgba(255, 255, 255, 0.3);
|
||
color: #ffffff;
|
||
padding: 10px 30px;
|
||
border-radius: 25px;
|
||
font-size: 18px;
|
||
font-weight: 500;
|
||
transition: all 0.3s ease;
|
||
|
||
/* Hover */
|
||
background: #ffffff;
|
||
color: #2e1065; /* Dark purple text on white */
|
||
border-color: #ffffff;
|
||
```
|
||
|
||
**Tailwind:**
|
||
|
||
```html
|
||
<button class="btn-secondary">Abbrechen</button>
|
||
```
|
||
|
||
**CSS Klasse (Tailwind Config):**
|
||
|
||
```css
|
||
.btn-secondary {
|
||
@apply inline-block relative;
|
||
@apply px-[30px] py-[10px];
|
||
@apply text-lg font-medium text-white;
|
||
@apply rounded-[25px];
|
||
@apply bg-transparent border-2 border-white/30;
|
||
@apply transition-all duration-300;
|
||
@apply hover:bg-white hover:text-purple-darkest hover:border-white;
|
||
}
|
||
```
|
||
|
||
#### Destructive Button
|
||
|
||
**Verwendung:** Gefährliche/irreversible Aktionen (z.B. "Konto löschen", "Bestellung stornieren", "Aus Warenkorb entfernen")
|
||
|
||
**Style:**
|
||
|
||
```css
|
||
background: #ea5b0c;
|
||
background-image: linear-gradient(to left, #ea5b0c, #ea5b0c, #c7490a, #ea5b0c);
|
||
background-size: 300%;
|
||
color: #ffffff;
|
||
padding: 10px 30px;
|
||
border-radius: 25px;
|
||
font-size: 18px;
|
||
font-weight: 500;
|
||
transition: background-position 1s, all 0.3s ease;
|
||
|
||
/* Hover */
|
||
background-position: 100%;
|
||
```
|
||
|
||
**Tailwind:**
|
||
|
||
```html
|
||
<button class="btn-destructive">Aus Warenkorb entfernen</button>
|
||
```
|
||
|
||
**CSS Klasse (Tailwind Config):**
|
||
|
||
```css
|
||
.btn-destructive {
|
||
@apply inline-block relative;
|
||
@apply px-[30px] py-[10px];
|
||
@apply text-lg font-medium text-white;
|
||
@apply rounded-[25px];
|
||
@apply cursor-pointer;
|
||
@apply border-0 outline-0;
|
||
@apply no-underline;
|
||
background: #ea5b0c;
|
||
background-image: linear-gradient(to left, #ea5b0c, #ea5b0c, #c7490a, #ea5b0c);
|
||
background-size: 300%;
|
||
background-position: 0%;
|
||
line-height: 1.7em;
|
||
transition: background-position 1s, all 0.3s ease;
|
||
}
|
||
|
||
.btn-destructive:hover {
|
||
background-position: 100%;
|
||
}
|
||
```
|
||
|
||
**Design-Rationale:**
|
||
- **EXP Signalorange** (#ea5b0c) aus dem offiziellen experimenta Styleguide
|
||
- Signalisiert "Vorsicht" und "Gefahr" (stärker als gelbes Orange, weniger aggressiv als reines Rot)
|
||
- Konsistentes Animations-Pattern wie Primary Button (1s Gradient-Shift)
|
||
- Klar unterscheidbar vom Primary Button (Pink/Rot vs. Signal-Orange)
|
||
- Offizielle CI-Farbe für Warnungen und destruktive Aktionen
|
||
|
||
#### Button Sizes
|
||
|
||
```html
|
||
<!-- Large (default) -->
|
||
<button class="btn-primary text-lg px-8 py-2.5">
|
||
<!-- Medium -->
|
||
<button class="btn-primary text-base px-6 py-2">
|
||
<!-- Small (mobile) -->
|
||
<button class="btn-primary text-base px-6 py-2 md:px-8 md:py-2.5"></button>
|
||
</button>
|
||
</button>
|
||
```
|
||
|
||
---
|
||
|
||
### 2. Cards
|
||
|
||
#### Glass-morphism Card (Main Pattern)
|
||
|
||
**Style:**
|
||
|
||
```css
|
||
background: linear-gradient(135deg, rgba(255, 255, 255, 0.1), rgba(255, 255, 255, 0.05));
|
||
backdrop-filter: blur(15px);
|
||
border-radius: 20px;
|
||
border: 1px solid rgba(255, 255, 255, 0.2);
|
||
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.3);
|
||
padding: 60px 40px;
|
||
```
|
||
|
||
**Tailwind:**
|
||
|
||
```html
|
||
<div class="card-glass">
|
||
<!-- Content -->
|
||
</div>
|
||
```
|
||
|
||
**CSS Klasse:**
|
||
|
||
```css
|
||
.card-glass {
|
||
@apply bg-gradient-to-br from-white/10 to-white/5;
|
||
@apply backdrop-blur-xl;
|
||
@apply rounded-2xl border border-white/20;
|
||
@apply shadow-2xl;
|
||
@apply p-15 md:p-10 sm:p-8;
|
||
}
|
||
```
|
||
|
||
#### Info Section Card
|
||
|
||
**Style:**
|
||
|
||
```css
|
||
background: rgba(255, 255, 255, 0.08);
|
||
border-radius: 12px;
|
||
padding: 30px;
|
||
border-left: 4px solid #f59d24;
|
||
```
|
||
|
||
**Tailwind:**
|
||
|
||
```html
|
||
<div class="card-info">
|
||
<h3 class="text-accent font-medium mb-4">Überschrift</h3>
|
||
<p class="text-white/90">Inhalt...</p>
|
||
</div>
|
||
```
|
||
|
||
**CSS Klasse:**
|
||
|
||
```css
|
||
.card-info {
|
||
@apply bg-white/8 rounded-xl;
|
||
@apply p-8 md:p-6 sm:p-5;
|
||
@apply border-l-4 border-accent;
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 3. Status Messages
|
||
|
||
#### Success Message
|
||
|
||
```html
|
||
<div class="status-message status-success">
|
||
<div class="status-icon">✓</div>
|
||
<h1>Verlängerung erfolgreich!</h1>
|
||
<p>Ihre Jahreskarte wurde verlängert.</p>
|
||
</div>
|
||
```
|
||
|
||
**CSS:**
|
||
|
||
```css
|
||
.status-icon {
|
||
@apply flex items-center justify-center;
|
||
@apply w-25 h-25 rounded-full;
|
||
@apply text-6xl text-white;
|
||
@apply mb-8;
|
||
@apply animate-pulse;
|
||
}
|
||
|
||
.status-success .status-icon {
|
||
@apply bg-success;
|
||
}
|
||
```
|
||
|
||
#### Error Message
|
||
|
||
```html
|
||
<div class="status-message status-error">
|
||
<div class="status-icon">✖</div>
|
||
<h1>Ein Fehler ist aufgetreten</h1>
|
||
<p>Bitte versuchen Sie es erneut.</p>
|
||
</div>
|
||
```
|
||
|
||
```css
|
||
.status-error .status-icon {
|
||
@apply bg-error;
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 4. Progress Bar
|
||
|
||
```html
|
||
<div class="progress-container">
|
||
<div class="progress-header">
|
||
<h3 class="progress-title">Verlängerungsfortschritt</h3>
|
||
<div class="progress-stats">5 / 10</div>
|
||
</div>
|
||
|
||
<div class="progress-bar-wrapper">
|
||
<div class="progress-bar" style="width: 50%"></div>
|
||
<div class="progress-percentage">50%</div>
|
||
</div>
|
||
</div>
|
||
```
|
||
|
||
**CSS:**
|
||
|
||
```css
|
||
.progress-container {
|
||
@apply bg-white/8 rounded-2xl;
|
||
@apply p-8 md:p-6;
|
||
@apply border-l-4 border-accent;
|
||
}
|
||
|
||
.progress-bar-wrapper {
|
||
@apply relative w-full h-8;
|
||
@apply bg-white/10 rounded-full;
|
||
@apply overflow-hidden;
|
||
@apply shadow-inner;
|
||
}
|
||
|
||
.progress-bar {
|
||
@apply h-full rounded-full;
|
||
@apply bg-gradient-to-r from-success via-[#66d96a] to-success;
|
||
@apply bg-[length:200%] animate-shimmer;
|
||
@apply transition-all duration-500;
|
||
}
|
||
|
||
.progress-percentage {
|
||
@apply absolute inset-0;
|
||
@apply flex items-center justify-center;
|
||
@apply text-base font-semibold text-white;
|
||
@apply drop-shadow-lg;
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 5. Forms
|
||
|
||
#### Input Field
|
||
|
||
```html
|
||
<div class="form-field">
|
||
<label for="email" class="form-label">E-Mail-Adresse</label>
|
||
<input type="email" id="email" class="form-input" placeholder="ihre.email@example.com" />
|
||
</div>
|
||
```
|
||
|
||
**CSS:**
|
||
|
||
```css
|
||
.form-label {
|
||
@apply block text-lg font-medium text-white/90;
|
||
@apply mb-3;
|
||
}
|
||
|
||
.form-input {
|
||
@apply w-full px-4 py-3;
|
||
@apply bg-white/10 border border-white/20;
|
||
@apply rounded-xl;
|
||
@apply text-white placeholder:text-white/50;
|
||
@apply focus:outline-none focus:ring-2 focus:ring-accent;
|
||
@apply transition-all duration-300;
|
||
}
|
||
|
||
.form-input:hover {
|
||
@apply bg-white/15;
|
||
}
|
||
```
|
||
|
||
#### Checkbox
|
||
|
||
```html
|
||
<label class="form-checkbox">
|
||
<input type="checkbox" class="checkbox-input" />
|
||
<span class="checkbox-label">Adresse für zukünftige Bestellungen speichern</span>
|
||
</label>
|
||
```
|
||
|
||
**CSS:**
|
||
|
||
```css
|
||
.form-checkbox {
|
||
@apply flex items-start gap-3 cursor-pointer;
|
||
}
|
||
|
||
.checkbox-input {
|
||
@apply w-5 h-5 mt-0.5;
|
||
@apply rounded border-2 border-white/30;
|
||
@apply bg-white/10;
|
||
@apply checked:bg-accent checked:border-accent;
|
||
@apply focus:ring-2 focus:ring-accent;
|
||
@apply cursor-pointer;
|
||
}
|
||
|
||
.checkbox-label {
|
||
@apply text-base text-white/90;
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 6. Links
|
||
|
||
```html
|
||
<a href="#" class="link-primary">Mehr erfahren</a> <a href="#" class="link-accent">Hier klicken</a>
|
||
```
|
||
|
||
**CSS:**
|
||
|
||
```css
|
||
.link-primary {
|
||
@apply text-primary underline;
|
||
@apply font-medium;
|
||
@apply transition-colors duration-300;
|
||
@apply hover:text-primary-light;
|
||
}
|
||
|
||
.link-accent {
|
||
@apply text-accent underline;
|
||
@apply font-medium;
|
||
@apply transition-colors duration-300;
|
||
@apply hover:text-accent-hover;
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 7. Logo
|
||
|
||
**SVG Logo** (Experimenta X-Logo)
|
||
|
||
Wird in den Design-Vorlagen verwendet. Sollte als Vue-Komponente gespeichert werden:
|
||
|
||
```vue
|
||
<!-- components/ExperimentaLogo.vue -->
|
||
<template>
|
||
<svg
|
||
class="logo"
|
||
viewBox="0 0 382.94 87.17"
|
||
xmlns="http://www.w3.org/2000/svg"
|
||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||
>
|
||
<!-- SVG paths from design examples -->
|
||
</svg>
|
||
</template>
|
||
|
||
<style scoped>
|
||
.logo {
|
||
width: 300px;
|
||
height: auto;
|
||
filter: drop-shadow(0 4px 8px rgba(0, 0, 0, 0.3));
|
||
}
|
||
|
||
/* Tablet */
|
||
@media (max-width: 768px) {
|
||
.logo {
|
||
width: 250px;
|
||
}
|
||
}
|
||
|
||
/* Mobile */
|
||
@media (max-width: 480px) {
|
||
.logo {
|
||
width: 200px;
|
||
}
|
||
}
|
||
</style>
|
||
```
|
||
|
||
---
|
||
|
||
### 8. Icons
|
||
|
||
**Icon Library:** [Lucide Vue Next](https://lucide.dev) (bereits installiert)
|
||
|
||
Das Projekt verwendet **lucide-vue-next** für alle Icons. Lucide bietet über 1.500+ hochwertige, konsistente Icons, die perfekt mit shadcn-nuxt und unserem Design System harmonieren.
|
||
|
||
#### Installation
|
||
|
||
```bash
|
||
# Bereits installiert in package.json
|
||
pnpm add lucide-vue-next
|
||
```
|
||
|
||
#### Verwendung
|
||
|
||
**Import:**
|
||
|
||
```vue
|
||
<script setup lang="ts">
|
||
// Named imports für tree-shaking (empfohlen)
|
||
import { Mail, Lock, CheckCircle, AlertCircle, Info, X } from 'lucide-vue-next'
|
||
</script>
|
||
|
||
<template>
|
||
<!-- Icon mit Standard-Größe -->
|
||
<Mail />
|
||
|
||
<!-- Icon mit Custom-Größe und Farbe -->
|
||
<Mail :size="24" class="text-accent" />
|
||
|
||
<!-- Icon mit Tailwind-Klassen -->
|
||
<CheckCircle class="w-6 h-6 text-success" />
|
||
</template>
|
||
```
|
||
|
||
#### Häufig verwendete Icons
|
||
|
||
```vue
|
||
<script setup lang="ts">
|
||
import {
|
||
// Auth & User
|
||
Mail,
|
||
Lock,
|
||
User,
|
||
UserCircle,
|
||
LogIn,
|
||
LogOut,
|
||
|
||
// Shopping
|
||
ShoppingCart,
|
||
CreditCard,
|
||
Package,
|
||
|
||
// Navigation
|
||
ChevronRight,
|
||
ChevronLeft,
|
||
ChevronDown,
|
||
Menu,
|
||
X,
|
||
|
||
// Status & Feedback
|
||
CheckCircle,
|
||
AlertCircle,
|
||
AlertTriangle,
|
||
Info,
|
||
XCircle,
|
||
|
||
// Actions
|
||
Trash2,
|
||
Edit,
|
||
Plus,
|
||
Minus,
|
||
Search,
|
||
} from 'lucide-vue-next'
|
||
</script>
|
||
```
|
||
|
||
#### Icons in Komponenten
|
||
|
||
**Alert mit Icon:**
|
||
|
||
```vue
|
||
<script setup lang="ts">
|
||
import { AlertCircle } from 'lucide-vue-next'
|
||
</script>
|
||
|
||
<template>
|
||
<Alert variant="error">
|
||
<AlertCircle class="h-4 w-4" />
|
||
<AlertTitle>Fehler</AlertTitle>
|
||
<AlertDescription> Ein Fehler ist aufgetreten. Bitte versuchen Sie es erneut. </AlertDescription>
|
||
</Alert>
|
||
</template>
|
||
```
|
||
|
||
**Button mit Icon:**
|
||
|
||
```vue
|
||
<script setup lang="ts">
|
||
import { ShoppingCart } from 'lucide-vue-next'
|
||
</script>
|
||
|
||
<template>
|
||
<button class="btn-primary flex items-center gap-2">
|
||
<ShoppingCart :size="20" />
|
||
<span>In den Warenkorb</span>
|
||
</button>
|
||
</template>
|
||
```
|
||
|
||
**Login Form mit Icons:**
|
||
|
||
```vue
|
||
<script setup lang="ts">
|
||
import { Mail, Lock } from 'lucide-vue-next'
|
||
</script>
|
||
|
||
<template>
|
||
<form class="space-y-6">
|
||
<!-- E-Mail Input -->
|
||
<div class="form-field">
|
||
<label for="email" class="form-label flex items-center gap-2">
|
||
<Mail :size="18" class="text-accent" />
|
||
<span>E-Mail-Adresse</span>
|
||
</label>
|
||
<input type="email" id="email" class="form-input" />
|
||
</div>
|
||
|
||
<!-- Password Input -->
|
||
<div class="form-field">
|
||
<label for="password" class="form-label flex items-center gap-2">
|
||
<Lock :size="18" class="text-accent" />
|
||
<span>Passwort</span>
|
||
</label>
|
||
<input type="password" id="password" class="form-input" />
|
||
</div>
|
||
</form>
|
||
</template>
|
||
```
|
||
|
||
#### Icon-Größen
|
||
|
||
```vue
|
||
<!-- Extra Small (16px) -->
|
||
<Mail :size="16" />
|
||
|
||
<!-- Small (20px) - Standard für Buttons -->
|
||
<Mail :size="20" />
|
||
|
||
<!-- Medium (24px) - Standard für Inputs -->
|
||
<Mail :size="24" />
|
||
|
||
<!-- Large (32px) - Status Icons -->
|
||
<CheckCircle :size="32" />
|
||
|
||
<!-- Custom mit Tailwind -->
|
||
<Mail class="w-8 h-8" />
|
||
```
|
||
|
||
#### Icon-Farben
|
||
|
||
```vue
|
||
<!-- Experimenta Colors -->
|
||
<Mail class="text-experimenta-primary" />
|
||
<CheckCircle class="text-experimenta-accent" />
|
||
<AlertTriangle class="text-experimenta-red" />
|
||
|
||
<!-- Semantic Colors -->
|
||
<CheckCircle class="text-success" />
|
||
<AlertCircle class="text-error" />
|
||
<AlertTriangle class="text-warning" />
|
||
<Info class="text-info" />
|
||
|
||
<!-- White/Muted -->
|
||
<Mail class="text-white" />
|
||
<Mail class="text-white/90" />
|
||
<Mail class="text-white/70" />
|
||
```
|
||
|
||
#### Status Icons Pattern
|
||
|
||
Für Status-Meldungen verwenden wir konsistente Icons:
|
||
|
||
```vue
|
||
<script setup lang="ts">
|
||
import { CheckCircle, XCircle, AlertTriangle, Info } from 'lucide-vue-next'
|
||
</script>
|
||
|
||
<template>
|
||
<!-- Success -->
|
||
<div class="flex items-center gap-3 text-success">
|
||
<CheckCircle :size="24" />
|
||
<span>Erfolgreich!</span>
|
||
</div>
|
||
|
||
<!-- Error -->
|
||
<div class="flex items-center gap-3 text-error">
|
||
<XCircle :size="24" />
|
||
<span>Fehler aufgetreten</span>
|
||
</div>
|
||
|
||
<!-- Warning -->
|
||
<div class="flex items-center gap-3 text-warning">
|
||
<AlertTriangle :size="24" />
|
||
<span>Achtung!</span>
|
||
</div>
|
||
|
||
<!-- Info -->
|
||
<div class="flex items-center gap-3 text-info">
|
||
<Info :size="24" />
|
||
<span>Hinweis</span>
|
||
</div>
|
||
</template>
|
||
```
|
||
|
||
#### Best Practices
|
||
|
||
1. **Tree-Shaking:** Nutze Named Imports statt `import * as Icons`
|
||
|
||
```vue
|
||
✅ import { Mail, Lock } from 'lucide-vue-next'
|
||
❌ import * as Icons from 'lucide-vue-next'
|
||
```
|
||
|
||
2. **Accessibility:** Verwende `aria-label` wenn Icons ohne Text stehen
|
||
|
||
```vue
|
||
<button aria-label="Schließen">
|
||
<X :size="20" />
|
||
</button>
|
||
```
|
||
|
||
3. **Konsistenz:** Verwende innerhalb einer Komponente einheitliche Icon-Größen
|
||
|
||
4. **Farben:** Nutze Tailwind-Klassen für Farben statt inline-Styles
|
||
|
||
5. **Stroke Width:** Lucide Icons haben eine Standardstärke von 2. Für dünnere/dickere Linien:
|
||
```vue
|
||
<Mail :size="24" :stroke-width="1.5" />
|
||
```
|
||
|
||
#### Icon-Übersicht
|
||
|
||
Alle verfügbaren Icons: [https://lucide.dev/icons/](https://lucide.dev/icons/)
|
||
|
||
**Kategorien:**
|
||
|
||
- **Arrows & Chevrons:** ChevronRight, ArrowRight, ChevronDown
|
||
- **Shopping:** ShoppingCart, CreditCard, Package, Truck
|
||
- **User & Auth:** User, UserCircle, LogIn, LogOut, Lock, Key
|
||
- **Status:** CheckCircle, XCircle, AlertTriangle, Info
|
||
- **Actions:** Plus, Minus, Edit, Trash2, Search, Filter
|
||
- **Media:** Image, File, FileText, Download, Upload
|
||
- **Navigation:** Menu, X, Home, Settings, HelpCircle
|
||
|
||
---
|
||
|
||
## Animationen & Transitions
|
||
|
||
### Pulse (für Status Icons)
|
||
|
||
```css
|
||
@keyframes pulse {
|
||
0%,
|
||
100% {
|
||
transform: scale(1);
|
||
}
|
||
50% {
|
||
transform: scale(1.1);
|
||
}
|
||
}
|
||
|
||
.animate-pulse {
|
||
animation: pulse 2s ease-in-out infinite;
|
||
}
|
||
```
|
||
|
||
### Shimmer (für Progress Bars)
|
||
|
||
```css
|
||
@keyframes shimmer {
|
||
0% {
|
||
background-position: -200% 0;
|
||
}
|
||
100% {
|
||
background-position: 200% 0;
|
||
}
|
||
}
|
||
|
||
.animate-shimmer {
|
||
animation: shimmer 3s ease-in-out infinite;
|
||
}
|
||
```
|
||
|
||
### Button Gradient Animation
|
||
|
||
```css
|
||
.btn-primary {
|
||
background-size: 300%;
|
||
background-position: left;
|
||
transition:
|
||
background-position 1s ease,
|
||
all 0.3s ease;
|
||
}
|
||
|
||
.btn-primary:hover {
|
||
background-position: right;
|
||
}
|
||
```
|
||
|
||
### Hover Transitions
|
||
|
||
```css
|
||
/* Standard Hover */
|
||
.hover-scale {
|
||
@apply transition-transform duration-300;
|
||
@apply hover:scale-105;
|
||
}
|
||
|
||
/* Logo Hover */
|
||
.logo:hover {
|
||
transform: scale(1.05);
|
||
transition: all 0.3s ease;
|
||
}
|
||
|
||
/* Social Links Hover */
|
||
.social-link:hover {
|
||
transform: translateY(-3px);
|
||
transition: all 0.3s ease;
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## Accessibility
|
||
|
||
### Farb-Kontraste
|
||
|
||
Alle Text-Farben wurden auf **WCAG AA Standard** getestet:
|
||
|
||
- **Weiß auf Dark Purple**: ✅ AAA (Kontrast > 7:1)
|
||
- **Magenta Buttons**: ✅ AA (Kontrast > 4.5:1)
|
||
- **Orange Akzente**: ✅ AA (Kontrast > 4.5:1)
|
||
|
||
### Focus States
|
||
|
||
```css
|
||
/* Alle interaktiven Elemente */
|
||
.focus-visible {
|
||
@apply focus:outline-none focus:ring-2 focus:ring-accent focus:ring-offset-2 focus:ring-offset-purple-darkest;
|
||
}
|
||
```
|
||
|
||
### Screen Reader Support
|
||
|
||
```html
|
||
<!-- Buttons -->
|
||
<button aria-label="Zur experimenta Startseite zurückkehren">Zurück</button>
|
||
|
||
<!-- Status Messages -->
|
||
<div role="alert" aria-live="polite">
|
||
<p>Ihre Jahreskarte wurde erfolgreich verlängert.</p>
|
||
</div>
|
||
```
|
||
|
||
### Keyboard Navigation
|
||
|
||
- **Tab-Reihenfolge**: Logisch von oben nach unten
|
||
- **Focus Indicators**: Sichtbarer Fokus-Ring auf allen interaktiven Elementen
|
||
- **Skip Links**: "Zum Hauptinhalt springen" Link am Anfang
|
||
|
||
---
|
||
|
||
## Verwendung in Nuxt 4
|
||
|
||
### 1. Tailwind Config importieren
|
||
|
||
Siehe `tailwind.config.ts` für die vollständige Theme-Konfiguration.
|
||
|
||
### 2. Komponenten verwenden
|
||
|
||
```vue
|
||
<template>
|
||
<div class="card-glass">
|
||
<div class="status-icon bg-success">✓</div>
|
||
<h1 class="text-4xl md:text-3xl sm:text-2xl font-light tracking-tight mb-8">Erfolgreich!</h1>
|
||
<p class="text-lg md:text-base leading-relaxed text-white/90">Ihre Aktion war erfolgreich.</p>
|
||
|
||
<button class="btn-primary mt-8">Weiter</button>
|
||
</div>
|
||
</template>
|
||
```
|
||
|
||
### 3. shadcn-nuxt Komponenten anpassen
|
||
|
||
Die shadcn-nuxt Komponenten können mit den experimenta-Farben überschrieben werden:
|
||
|
||
```vue
|
||
<!-- components/ui/button/Button.vue -->
|
||
<Button class="btn-primary">Click me</Button>
|
||
```
|
||
|
||
---
|
||
|
||
## Beispiel: Complete Page Layout
|
||
|
||
```vue
|
||
<template>
|
||
<div class="min-h-screen bg-gradient-primary">
|
||
<!-- Header -->
|
||
<header class="bg-header backdrop-blur-lg sticky top-0 z-50 py-8">
|
||
<div class="container-wide mx-auto px-5">
|
||
<ExperimentaLogo />
|
||
</div>
|
||
</header>
|
||
|
||
<!-- Main Content -->
|
||
<main class="container-main mx-auto px-5 py-10">
|
||
<div class="card-glass">
|
||
<!-- Success Icon -->
|
||
<div class="status-icon bg-success">✓</div>
|
||
|
||
<!-- Headline -->
|
||
<h1 class="text-4xl md:text-3xl sm:text-2xl font-light tracking-tight mb-8">
|
||
Verlängerung erfolgreich!
|
||
</h1>
|
||
|
||
<!-- Body Text -->
|
||
<p class="text-lg md:text-base leading-relaxed text-white/90 mb-6">
|
||
Ihre Pädagogische Jahreskarte wurde erfolgreich verlängert.
|
||
</p>
|
||
|
||
<!-- Info Section -->
|
||
<div class="card-info mt-8">
|
||
<h3 class="text-accent font-medium text-lg mb-4">Ihre Vorteile</h3>
|
||
<p class="text-white/90">
|
||
Mit der Jahreskarte erhalten Sie ein Jahr lang freien Eintritt...
|
||
</p>
|
||
</div>
|
||
|
||
<!-- Button -->
|
||
<button class="btn-primary mt-8">Zur experimenta Startseite</button>
|
||
</div>
|
||
</main>
|
||
|
||
<!-- Footer -->
|
||
<footer class="bg-footer mt-20">
|
||
<div class="container-wide mx-auto px-5 py-15">
|
||
<div
|
||
class="border-t border-white/10 pt-8 flex flex-wrap justify-between items-center gap-5"
|
||
>
|
||
<p class="text-white/80">
|
||
© 2025 experimenta gGmbH – Das Science Center. Alle Rechte vorbehalten.
|
||
</p>
|
||
<div class="flex gap-8">
|
||
<a href="#" class="link-primary">Kontakt</a>
|
||
<a href="#" class="link-primary">Impressum</a>
|
||
<a href="#" class="link-primary">Datenschutz</a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</footer>
|
||
</div>
|
||
</template>
|
||
```
|
||
|
||
---
|
||
|
||
## Weiterführende Ressourcen
|
||
|
||
- **Roboto Font:** [Google Fonts](https://fonts.google.com/specimen/Roboto)
|
||
- **Tailwind CSS v4:** [Tailwind Docs](https://tailwindcss.com/docs)
|
||
- **shadcn-nuxt:** [shadcn-nuxt Docs](https://www.shadcn-vue.com/docs/installation/nuxt.html)
|
||
- **WCAG Accessibility:** [WebAIM Contrast Checker](https://webaim.org/resources/contrastchecker/)
|
||
|
||
---
|
||
|
||
**Maintainer:** Experimenta Team
|
||
**Fragen?** → `docs@experimenta.science`
|