You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

27 KiB

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
  2. Typografie
  3. Spacing & Layout
  4. Komponenten
  5. Animationen & Transitions
  6. Accessibility

Farbpalette

Primärfarben

Experimenta Magenta (Hauptfarbe)

--color-primary: #e6007e;
--color-primary-hover: #c2006a;
--color-primary-light: #ff4081;

Verwendung: Primary Buttons, Links, aktive Zustände, Brand-Elemente

Experimenta Pink

--color-secondary: #e91e63;
--color-secondary-dark: #c2185b;

Verwendung: Secondary Buttons, Footer Headings, Social Media Icons

Experimenta Orange (Akzent)

--color-accent: #f59d24;
--color-accent-hover: #ffb347;

Verwendung: Border-Akzente (links), Hover-Effekte, Highlights, Labels

Experimenta Rot (Button-Gradient)

--color-red: #e40521;

Verwendung: Button-Gradienten, Error-Zustände (zusammen mit Magenta)

Background-Farben

Dark Gradient (Haupt-Background)

--bg-gradient-primary: linear-gradient(135deg, #2e1065 0%, #1a0a3a 50%, #0f051d 100%);

Purple Variants

--color-purple-dark: #2e1065; /* Start des Gradienten */
--color-purple-deeper: #1a0a3a; /* Mitte des Gradienten */
--color-purple-darkest: #0f051d; /* Ende des Gradienten */

Header Background

--bg-header: rgba(46, 16, 101, 0.95); /* Mit backdrop-filter: blur(10px) */

Footer Background

--bg-footer: linear-gradient(135deg, #1a0a3a 0%, #0f051d 100%);

Glassmorphism (Cards & Containers)

--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)

--bg-section: rgba(255, 255, 255, 0.08); /* Leicht heller als Card */
--bg-section-hover: rgba(255, 255, 255, 0.15);

Semantische Farben

Success

--color-success: #46c74a;
--color-success-dark: #3ba83e;
--color-success-gradient: linear-gradient(90deg, #46c74a 0%, #66d96a 50%, #46c74a 100%);

Error

--color-error: #e53e3e;
--color-error-dark: #c53030;

Warning

--color-warning: #f59d24;
--color-warning-dark: #dd8a1e;

Info

--color-info: #4299e1;
--color-info-dark: #3182ce;

Text-Farben

--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

--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)

font-family: 'Roboto', sans-serif;

Lokales Hosting:

Die Roboto-Schrift wird lokal aus /public/fonts/roboto/ geladen:

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 → 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):

H1: 28px
H2: 24px
H3: 20px
Body: 16px

Mobile (≤480px):

H1: 24px
H2: 20px
H3: 18px
Body: 14px

Tailwind Klassen

<!-- 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)

--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

--container-main: 800px; /* Main Content (forms, text) */
--container-wide: 1200px; /* Footer, wide sections */
--container-full: 1760px; /* Full-width content (aus Website) */

Border-Radius

--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

/* Mobile First */
--breakpoint-sm: 480px; /* Small phones */
--breakpoint-md: 768px; /* Tablets */
--breakpoint-lg: 1024px; /* Small desktops */
--breakpoint-xl: 1280px; /* Large desktops */

Verwendung in Tailwind:

<!-- Mobile First: base = mobile, md = tablet, lg = desktop -->
<div class="p-4 md:p-8 lg:p-15"></div>

Standard Paddings

Cards:

/* Desktop */
padding: 60px 40px;

/* Tablet */
@media (max-width: 768px) {
  padding: 40px 20px;
}

/* Mobile */
@media (max-width: 480px) {
  padding: 30px 15px;
}

Sections:

padding: 30px;

/* Tablet */
@media (max-width: 768px) {
  padding: 25px 20px;
}

/* Mobile */
@media (max-width: 480px) {
  padding: 20px 15px;
}

Komponenten

1. Buttons

Primary Button

Style:

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:

<button class="btn-primary">Zur experimenta Startseite</button>

CSS Klasse (Tailwind Config):

.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:

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:

<button class="btn-secondary">Abbrechen</button>

CSS Klasse (Tailwind Config):

.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:

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:

<button class="btn-destructive">Aus Warenkorb entfernen</button>

CSS Klasse (Tailwind Config):

.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

<!-- 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:

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:

<div class="card-glass">
  <!-- Content -->
</div>

CSS Klasse:

.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:

background: rgba(255, 255, 255, 0.08);
border-radius: 12px;
padding: 30px;
border-left: 4px solid #f59d24;

Tailwind:

<div class="card-info">
  <h3 class="text-accent font-medium mb-4">Überschrift</h3>
  <p class="text-white/90">Inhalt...</p>
</div>

CSS Klasse:

.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

<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:

.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

<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>
.status-error .status-icon {
  @apply bg-error;
}

4. Progress Bar

<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:

.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

<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:

.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

<label class="form-checkbox">
  <input type="checkbox" class="checkbox-input" />
  <span class="checkbox-label">Adresse für zukünftige Bestellungen speichern</span>
</label>

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;
}

<a href="#" class="link-primary">Mehr erfahren</a> <a href="#" class="link-accent">Hier klicken</a>

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;
}

SVG Logo (Experimenta X-Logo)

Wird in den Design-Vorlagen verwendet. Sollte als Vue-Komponente gespeichert werden:

<!-- 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 (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

# Bereits installiert in package.json
pnpm add lucide-vue-next

Verwendung

Import:

<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

<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:

<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:

<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:

<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

<!-- 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

<!-- 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:

<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

     import { Mail, Lock } from 'lucide-vue-next'
     import * as Icons from 'lucide-vue-next'
    
  2. Accessibility: Verwende aria-label wenn Icons ohne Text stehen

    <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:

    <Mail :size="24" :stroke-width="1.5" />
    

Icon-Übersicht

Alle verfügbaren 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)

@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)

@keyframes shimmer {
  0% {
    background-position: -200% 0;
  }
  100% {
    background-position: 200% 0;
  }
}

.animate-shimmer {
  animation: shimmer 3s ease-in-out infinite;
}

Button Gradient Animation

.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

/* 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

/* 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

<!-- 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

<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:

<!-- components/ui/button/Button.vue -->
<Button class="btn-primary">Click me</Button>

Beispiel: Complete Page Layout

<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


Maintainer: Experimenta Team Fragen?docs@experimenta.science