Skill

UI Theming Skill

One-time UI theming skill. Sets up design system (theme, tokens, typography). Run ONCE at project start before implementing features.

From byt8
Install
1
Run in your terminal
$
npx claudepluginhub byteagenten/byteagenten-marketplace --plugin byt8
Tool Access

This skill uses the workspace's default tool permissions.

Supporting Assets
View in Repository
theme-showcase.pdf
themes/arctic-frost.md
themes/botanical-garden.md
themes/desert-rose.md
themes/forest-canopy.md
themes/golden-hour.md
themes/midnight-galaxy.md
themes/modern-minimalist.md
themes/ocean-depths.md
themes/sunset-boulevard.md
themes/tech-innovation.md
Skill Content

UI Theming Skill

Initialize the design system. This skill should be run ONCE at project start to set up:

  • Color theme selection
  • Design token generation
  • Typography system
  • SCSS structure

Usage

/ui-theming

Workflow

Step 0: Check Existing Design System

Before creating files, check if a design system already exists:

ls frontend/src/styles/tokens/ 2>/dev/null

If directory exists with files, show:

⚠️ Design System bereits vorhanden!

Gefundene Dateien:
- _colors.scss
- _typography.scss
- [weitere Dateien...]

Optionen:
1. Abbrechen (bestehende Dateien behalten)
2. Überschreiben (Theme neu generieren)
3. Nur Theme-Preview generieren (keine Änderungen)

Wie möchten Sie fortfahren?
  • Option 1: Exit skill, no changes
  • Option 2: Continue with Step 1 (files will be overwritten)
  • Option 3: Skip to Step 7 (Theme-Auswahl + Preview generieren, keine SCSS-Änderungen)

If directory does not exist: Continue with Step 1.


Step 1: Theme Selection

Present the available themes:

Available Themes:

1. Ocean Depths     - Professional maritime (Blue/Teal)
2. Sunset Boulevard - Warm vibrant (Orange/Pink)
3. Forest Canopy    - Natural earth tones (Green/Brown)
4. Modern Minimalist - Clean grayscale (Gray/Black)
5. Golden Hour      - Rich autumnal (Gold/Orange)
6. Arctic Frost     - Cool crisp winter (Light Blue/White)
7. Desert Rose      - Soft sophisticated (Pink/Beige)
8. Tech Innovation  - Bold modern tech (Blue/Purple) [RECOMMENDED]
9. Botanical Garden - Fresh organic (Green/Cream)
10. Midnight Galaxy - Dramatic cosmic (Dark Purple/Blue)

Which theme would you like for your project?

Step 2: Read Selected Theme

After user selects a theme, read the theme file:

Read: ${CLAUDE_PLUGIN_ROOT}/skills/ui-theming/themes/[selected-theme].md

Extract:

  • Primary color
  • Secondary color
  • Font family
  • Font weights

Step 3: Farbvarianten berechnen

Aus den Theme-Farben (Primary + Accent) die Light/Dark-Varianten ableiten.

Algorithmus (HSL-Farbraum):

VarianteBerechnung
primary-lightLightness +20%, Saturation -10%
primary-darkLightness -20%, Saturation +5%
accent-lightLightness +20%, Saturation -10%
accent-darkLightness -20%, Saturation +5%

Beispiel: Primary #0066ff (HSL: 216°, 100%, 50%) → Light: HSL(216°, 90%, 70%) = #5c9aff → Dark: HSL(216°, 100%, 30%) = #003d99

Contrast-Farbe: Weiß (#ffffff) wenn Lightness < 50%, sonst Schwarz (#000000).

Dark-Mode Semantic Colors (fest definiert):

TokenLight ModeDark Mode
success#4caf50#81c784
warning#ff9800#ffb74d
error#f44336#e57373
info#2196f3#64b5f6

Step 4: Create Token Files

Create the following modular structure in frontend/src/styles/tokens/:

frontend/src/styles/
├── tokens/
│   ├── _colors.scss        # Color palette + light/dark mode
│   ├── _typography.scss    # Font system as CSS Custom Properties
│   ├── _spacing.scss       # 8pt grid + semantic aliases
│   ├── _elevation.scss     # Material elevation shadows
│   ├── _breakpoints.scss   # Responsive breakpoints + mixins
│   └── _index.scss         # Central export (@forward + theme mixins)
└── styles.scss             # Root file (@use tokens)

tokens/_colors.scss

// Color System - CSS Custom Properties
// Generated by /ui-theming
// Theme: [Selected Theme]

@mixin colors-light {
  // Brand Colors (from selected theme)
  --color-primary: [primary-hex];
  --color-primary-light: [primary-light-hex];
  --color-primary-dark: [primary-dark-hex];
  --color-primary-contrast: #ffffff;

  --color-accent: [accent-hex];
  --color-accent-light: [accent-light-hex];
  --color-accent-dark: [accent-dark-hex];
  --color-accent-contrast: #ffffff;

  // Semantic Colors
  --color-success: #4caf50;
  --color-warning: #ff9800;
  --color-error: #f44336;
  --color-info: #2196f3;

  // Neutral Palette
  --color-gray-50: #fafafa;
  --color-gray-100: #f5f5f5;
  --color-gray-200: #eeeeee;
  --color-gray-300: #e0e0e0;
  --color-gray-400: #bdbdbd;
  --color-gray-500: #9e9e9e;
  --color-gray-600: #757575;
  --color-gray-700: #616161;
  --color-gray-800: #424242;
  --color-gray-900: #212121;

  // Surface & Background
  --color-background: #fafafa;
  --color-surface: #ffffff;
  --color-surface-variant: #f5f5f5;

  // Text
  --color-text-primary: rgba(0, 0, 0, 0.87);
  --color-text-secondary: rgba(0, 0, 0, 0.6);
  --color-text-disabled: rgba(0, 0, 0, 0.38);
  --color-text-on-primary: #ffffff;

  // Borders
  --color-divider: rgba(0, 0, 0, 0.12);
  --color-border: rgba(0, 0, 0, 0.23);
}

@mixin colors-dark {
  --color-primary: [primary-light-hex];
  --color-primary-light: [primary-hex];
  --color-primary-dark: [primary-dark-hex];
  --color-primary-contrast: #000000;

  --color-accent: [accent-light-hex];
  --color-accent-contrast: #000000;

  --color-success: #81c784;
  --color-warning: #ffb74d;
  --color-error: #e57373;
  --color-info: #64b5f6;

  --color-gray-50: #212121;
  --color-gray-100: #303030;
  --color-gray-200: #424242;
  --color-gray-300: #616161;
  --color-gray-400: #757575;
  --color-gray-500: #9e9e9e;
  --color-gray-600: #bdbdbd;
  --color-gray-700: #e0e0e0;
  --color-gray-800: #eeeeee;
  --color-gray-900: #fafafa;

  --color-background: #121212;
  --color-surface: #1e1e1e;
  --color-surface-variant: #2c2c2c;

  --color-text-primary: rgba(255, 255, 255, 0.87);
  --color-text-secondary: rgba(255, 255, 255, 0.6);
  --color-text-disabled: rgba(255, 255, 255, 0.38);
  --color-text-on-primary: #000000;

  --color-divider: rgba(255, 255, 255, 0.12);
  --color-border: rgba(255, 255, 255, 0.23);
}

tokens/_typography.scss

// Typography System - CSS Custom Properties
// Generated by /ui-theming

@mixin typography {
  // Font Families (from selected theme)
  --font-family-base: '[theme-font]', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --font-family-mono: 'Roboto Mono', 'Consolas', monospace;

  // Font Sizes (Modular Scale 1.25)
  --font-size-xs: 0.75rem;
  --font-size-sm: 0.875rem;
  --font-size-base: 1rem;
  --font-size-lg: 1.125rem;
  --font-size-xl: 1.25rem;
  --font-size-2xl: 1.5rem;
  --font-size-3xl: 1.875rem;
  --font-size-4xl: 2.25rem;
  --font-size-5xl: 3rem;

  // Font Weights
  --font-weight-light: 300;
  --font-weight-regular: 400;
  --font-weight-medium: 500;
  --font-weight-bold: 700;

  // Line Heights
  --line-height-tight: 1.25;
  --line-height-base: 1.5;
  --line-height-relaxed: 1.75;

  // Letter Spacing
  --letter-spacing-tight: -0.025em;
  --letter-spacing-normal: 0;
  --letter-spacing-wide: 0.025em;

  // Semantic Typography Tokens
  --font-heading-1: var(--font-weight-light) var(--font-size-5xl) / var(--line-height-tight) var(--font-family-base);
  --font-heading-2: var(--font-weight-light) var(--font-size-4xl) / var(--line-height-tight) var(--font-family-base);
  --font-heading-3: var(--font-weight-regular) var(--font-size-3xl) / var(--line-height-tight) var(--font-family-base);
  --font-heading-4: var(--font-weight-regular) var(--font-size-2xl) / var(--line-height-base) var(--font-family-base);
  --font-heading-5: var(--font-weight-medium) var(--font-size-xl) / var(--line-height-base) var(--font-family-base);
  --font-heading-6: var(--font-weight-medium) var(--font-size-lg) / var(--line-height-base) var(--font-family-base);
  --font-body-1: var(--font-weight-regular) var(--font-size-base) / var(--line-height-base) var(--font-family-base);
  --font-body-2: var(--font-weight-regular) var(--font-size-sm) / var(--line-height-base) var(--font-family-base);
  --font-caption: var(--font-weight-regular) var(--font-size-xs) / var(--line-height-base) var(--font-family-base);
}

tokens/_spacing.scss

// Spacing System - 8pt Grid
// Generated by /ui-theming

@mixin spacing {
  // Base Scale
  --spacing-0: 0;
  --spacing-1: 0.25rem;    // 4px
  --spacing-2: 0.5rem;     // 8px
  --spacing-3: 0.75rem;    // 12px
  --spacing-4: 1rem;       // 16px
  --spacing-5: 1.25rem;    // 20px
  --spacing-6: 1.5rem;     // 24px
  --spacing-8: 2rem;       // 32px
  --spacing-10: 2.5rem;    // 40px
  --spacing-12: 3rem;      // 48px
  --spacing-16: 4rem;      // 64px

  // Semantic Aliases
  --spacing-page-x: var(--spacing-6);
  --spacing-page-y: var(--spacing-8);
  --spacing-section: var(--spacing-8);
  --spacing-card: var(--spacing-4);
  --spacing-inline: var(--spacing-2);

  // Border Radius
  --radius-none: 0;
  --radius-sm: 0.125rem;
  --radius-md: 0.25rem;
  --radius-lg: 0.5rem;
  --radius-xl: 1rem;
  --radius-full: 9999px;

  // Component Tokens
  --card-padding: var(--spacing-4);
  --card-radius: var(--radius-md);
  --button-padding-x: var(--spacing-4);
  --button-padding-y: var(--spacing-2);
  --button-radius: var(--radius-md);
  --input-padding-x: var(--spacing-4);
  --input-padding-y: var(--spacing-2);
  --input-radius: var(--radius-md);
  --table-cell-padding: var(--spacing-3) var(--spacing-4);
  --toolbar-height: 4rem;
  --sidenav-width: 16rem;
}

tokens/_elevation.scss

// Elevation & Shadows
// Generated by /ui-theming

@mixin elevation {
  // Material Design Elevation
  --elevation-0: none;
  --elevation-1: 0 2px 1px -1px rgba(0,0,0,.2), 0 1px 1px 0 rgba(0,0,0,.14), 0 1px 3px 0 rgba(0,0,0,.12);
  --elevation-2: 0 3px 1px -2px rgba(0,0,0,.2), 0 2px 2px 0 rgba(0,0,0,.14), 0 1px 5px 0 rgba(0,0,0,.12);
  --elevation-4: 0 2px 4px -1px rgba(0,0,0,.2), 0 4px 5px 0 rgba(0,0,0,.14), 0 1px 10px 0 rgba(0,0,0,.12);
  --elevation-8: 0 5px 5px -3px rgba(0,0,0,.2), 0 8px 10px 1px rgba(0,0,0,.14), 0 3px 14px 2px rgba(0,0,0,.12);
  --elevation-16: 0 8px 10px -5px rgba(0,0,0,.2), 0 16px 24px 2px rgba(0,0,0,.14), 0 6px 30px 5px rgba(0,0,0,.12);

  // Semantic Aliases
  --shadow-card: var(--elevation-1);
  --shadow-dropdown: var(--elevation-4);
  --shadow-modal: var(--elevation-16);

  // Transitions
  --transition-fast: 150ms ease-in-out;
  --transition-base: 250ms ease-in-out;
  --transition-slow: 350ms ease-in-out;

  // Z-Index Scale
  --z-dropdown: 1000;
  --z-sticky: 1020;
  --z-fixed: 1030;
  --z-modal-backdrop: 1040;
  --z-modal: 1050;
  --z-popover: 1060;
  --z-tooltip: 1070;
}

tokens/_breakpoints.scss

// Responsive Breakpoints
// Generated by /ui-theming

$breakpoint-sm: 600px;
$breakpoint-md: 960px;
$breakpoint-lg: 1280px;
$breakpoint-xl: 1920px;

// Breakpoint Mixins (use in components)
@mixin sm { @media (min-width: $breakpoint-sm) { @content; } }
@mixin md { @media (min-width: $breakpoint-md) { @content; } }
@mixin lg { @media (min-width: $breakpoint-lg) { @content; } }
@mixin xl { @media (min-width: $breakpoint-xl) { @content; } }

@mixin below-sm { @media (max-width: ($breakpoint-sm - 1)) { @content; } }
@mixin below-md { @media (max-width: ($breakpoint-md - 1)) { @content; } }
@mixin below-lg { @media (max-width: ($breakpoint-lg - 1)) { @content; } }

tokens/_index.scss

// Token System Entry Point
// Generated by /ui-theming
// Uses @forward/@use (modern SCSS module system)

@forward 'breakpoints';

@use 'colors';
@use 'typography';
@use 'spacing';
@use 'elevation';

// All tokens combined
@mixin all-tokens {
  @include typography.typography;
  @include spacing.spacing;
  @include elevation.elevation;
}

// Theme: Light (default)
@mixin theme-light {
  @include colors.colors-light;
  @include all-tokens;
}

// Theme: Dark
@mixin theme-dark {
  @include colors.colors-dark;
  @include all-tokens;
}

Step 5: Update styles.scss

Ensure frontend/src/styles.scss uses the token system:

@use 'styles/tokens' as tokens;

// Apply light theme by default
:root {
  @include tokens.theme-light;
}

// Dark mode support
@media (prefers-color-scheme: dark) {
  :root {
    @include tokens.theme-dark;
  }
}

// Manual dark mode toggle class
.dark-theme {
  @include tokens.theme-dark;
}

Step 6: Verify Setup

# Check file structure
ls -la frontend/src/styles/tokens/

# Build to verify no errors
cd frontend && npm run build

Step 7: Generate Theme Preview

7.1: Theme bestimmen

Wenn aus Step 6 kommend (voller Workflow): → Das in Step 1 gewählte Theme verwenden, keine erneute Abfrage.

Wenn direkt zu Step 7 gesprungen (Option 3 aus Step 0): → Theme-Auswahl anzeigen:

Welches Theme möchten Sie in der Preview sehen?

1. Ocean Depths     - Professional maritime (Blue/Teal)
2. Sunset Boulevard - Warm vibrant (Orange/Pink)
3. Forest Canopy    - Natural earth tones (Green/Brown)
4. Modern Minimalist - Clean grayscale (Gray/Black)
5. Golden Hour      - Rich autumnal (Gold/Orange)
6. Arctic Frost     - Cool crisp winter (Light Blue/White)
7. Desert Rose      - Soft sophisticated (Pink/Beige)
8. Tech Innovation  - Bold modern tech (Blue/Purple)
9. Botanical Garden - Fresh organic (Green/Cream)
10. Midnight Galaxy - Dramatic cosmic (Dark Purple/Blue)

Theme-Nummer eingeben:

7.2: Projekt-Elemente analysieren

Scanne das Projekt nach verwendeten UI-Elementen (Material UND native HTML):

# 1. Angular Material Komponenten
grep -roh "mat-[a-z-]*" frontend/src/app --include="*.html" | sort | uniq -c | sort -rn

# 2. Native HTML Elemente
grep -roE "<(table|form|input|select|textarea|button|ul|ol|nav|header|footer|aside|dialog|details|summary)[^>]*>" frontend/src/app --include="*.html" | sort | uniq -c | sort -rn

# 3. Custom Components (app-*)
grep -roh "app-[a-z-]*" frontend/src/app --include="*.html" | sort | uniq -c | sort -rn

Beispiel-Output:

=== Angular Material ===
  45 mat-button
  34 mat-form-field
  12 mat-table

=== Native HTML ===
  28 <table
  56 <input
  23 <select
  15 <button
  12 <ul
   8 <nav
   4 <dialog

=== Custom Components ===
  18 app-user-card
   9 app-status-badge
   5 app-data-grid

Element-Mapping für Preview:

Element (Material ODER Native)Preview-Sektion
mat-table ODER <table>Datentabelle
mat-form-field ODER <input>/<select>Formular
mat-button ODER <button>Buttons
mat-card ODER <article>/<section>Cards
mat-chip ODER .badge/.tagChips/Tags
mat-tab ODER Custom TabsTabs
<ul>/<ol>Listen
<nav>Navigation
<dialog> ODER mat-dialogDialoge
mat-progress-bar ODER <progress>Loading States
<details>/<summary>Accordions

Ergebnis speichern:

Gefundene UI-Elemente für Preview:

Material Components:
- [X] mat-button (45x)
- [X] mat-form-field (34x)
- [X] mat-table (12x)

Native HTML:
- [X] <table> (28x)
- [X] <input> (56x)
- [X] <ul> Listen (12x)
- [X] <nav> Navigation (8x)
- [ ] <dialog> (nicht verwendet)

Custom Components:
- [X] app-user-card (18x) → Card-Variante
- [X] app-status-badge (9x) → Chip/Badge-Variante

7.3: Theme-Datei lesen (nur bei Option 3)

Read: ${CLAUDE_PLUGIN_ROOT}/skills/ui-theming/themes/[selected-theme].md

Extrahiere Primary und Accent Color, berechne Light/Dark-Varianten (wie in Step 3).

7.4: Preview HTML erstellen (nur gefundene Komponenten)

Create wireframes/theme-preview-[theme-name].html - a standalone HTML file for instant visual feedback:

<!DOCTYPE html>
<html lang="de">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Theme Preview - [Theme Name]</title>
  <link href="https://fonts.googleapis.com/css2?family=[theme-font]:wght@300;400;500;700&display=swap" rel="stylesheet">
  <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
  <style>
    /* ========== GENERATED TOKENS (from _colors.scss) ========== */
    :root {
      /* Brand Colors */
      --color-primary: [primary-hex];
      --color-primary-light: [primary-light-hex];
      --color-primary-dark: [primary-dark-hex];
      --color-accent: [accent-hex];

      /* Semantic */
      --color-success: #4caf50;
      --color-warning: #ff9800;
      --color-error: #f44336;
      --color-info: #2196f3;

      /* Neutrals */
      --color-gray-100: #f5f5f5;
      --color-gray-200: #eeeeee;
      --color-gray-300: #e0e0e0;
      --color-gray-600: #757575;
      --color-gray-800: #424242;
      --color-gray-900: #212121;

      /* Surface */
      --color-background: #fafafa;
      --color-surface: #ffffff;
      --color-text-primary: rgba(0,0,0,0.87);
      --color-text-secondary: rgba(0,0,0,0.6);
      --color-divider: rgba(0,0,0,0.12);

      /* Typography */
      --font-family-base: '[theme-font]', sans-serif;

      /* Spacing */
      --spacing-2: 0.5rem;
      --spacing-3: 0.75rem;
      --spacing-4: 1rem;
      --spacing-6: 1.5rem;
      --radius-md: 0.25rem;

      /* Elevation */
      --elevation-1: 0 2px 1px -1px rgba(0,0,0,.2), 0 1px 1px 0 rgba(0,0,0,.14), 0 1px 3px 0 rgba(0,0,0,.12);
      --elevation-2: 0 3px 1px -2px rgba(0,0,0,.2), 0 2px 2px 0 rgba(0,0,0,.14), 0 1px 5px 0 rgba(0,0,0,.12);
    }

    .dark-theme {
      --color-primary: [primary-light-hex];
      --color-background: #121212;
      --color-surface: #1e1e1e;
      --color-text-primary: rgba(255,255,255,0.87);
      --color-text-secondary: rgba(255,255,255,0.6);
      --color-divider: rgba(255,255,255,0.12);
      --color-gray-100: #303030;
      --color-gray-200: #424242;
      --color-gray-300: #616161;
    }

    /* ========== BASE STYLES ========== */
    * { box-sizing: border-box; margin: 0; padding: 0; }
    body {
      font-family: var(--font-family-base);
      background: var(--color-background);
      color: var(--color-text-primary);
      padding: var(--spacing-6);
      transition: background 0.3s, color 0.3s;
    }

    .container { max-width: 1200px; margin: 0 auto; }

    h1 { font-size: 2.25rem; font-weight: 300; margin-bottom: var(--spacing-6); }
    h2 { font-size: 1.5rem; font-weight: 400; margin: var(--spacing-6) 0 var(--spacing-4); color: var(--color-text-secondary); }
    h3 { font-size: 1.25rem; font-weight: 500; margin-bottom: var(--spacing-3); }

    /* ========== THEME TOGGLE ========== */
    .theme-toggle {
      position: fixed; top: 1rem; right: 1rem;
      background: var(--color-surface); border: 1px solid var(--color-divider);
      padding: var(--spacing-2) var(--spacing-4); border-radius: var(--radius-md);
      cursor: pointer; box-shadow: var(--elevation-1);
    }

    /* ========== COLOR SWATCHES ========== */
    .swatches { display: flex; flex-wrap: wrap; gap: var(--spacing-3); }
    .swatch {
      width: 100px; height: 80px; border-radius: var(--radius-md);
      display: flex; flex-direction: column; justify-content: flex-end;
      padding: var(--spacing-2); font-size: 0.75rem; color: white;
      box-shadow: var(--elevation-1);
    }
    .swatch-label { font-weight: 500; }
    .swatch-hex { opacity: 0.8; }

    /* ========== CARD ========== */
    .card {
      background: var(--color-surface);
      border-radius: var(--radius-md);
      box-shadow: var(--elevation-1);
      padding: var(--spacing-4);
      margin-bottom: var(--spacing-4);
    }

    /* ========== BUTTONS ========== */
    .btn {
      display: inline-flex; align-items: center; gap: var(--spacing-2);
      padding: var(--spacing-2) var(--spacing-4);
      border: none; border-radius: var(--radius-md);
      font-family: inherit; font-size: 0.875rem; font-weight: 500;
      cursor: pointer; transition: all 0.2s;
    }
    .btn-primary { background: var(--color-primary); color: white; }
    .btn-primary:hover { filter: brightness(1.1); }
    .btn-secondary { background: transparent; color: var(--color-primary); border: 1px solid var(--color-divider); }
    .btn-danger { background: var(--color-error); color: white; }
    .btn-icon { padding: var(--spacing-2); min-width: auto; }

    /* ========== TABLE ========== */
    .table { width: 100%; border-collapse: collapse; }
    .table th, .table td {
      padding: var(--spacing-3) var(--spacing-4);
      text-align: left; border-bottom: 1px solid var(--color-divider);
    }
    .table th { font-weight: 500; color: var(--color-text-secondary); font-size: 0.75rem; text-transform: uppercase; }
    .table tr:hover { background: var(--color-gray-100); }
    .table-actions { display: flex; gap: var(--spacing-2); }

    /* ========== FORM ========== */
    .form-group { margin-bottom: var(--spacing-4); }
    .form-label { display: block; font-size: 0.875rem; color: var(--color-text-secondary); margin-bottom: var(--spacing-2); }
    .form-input {
      width: 100%; padding: var(--spacing-3) var(--spacing-4);
      border: 1px solid var(--color-divider); border-radius: var(--radius-md);
      font-family: inherit; font-size: 1rem;
      background: var(--color-surface); color: var(--color-text-primary);
    }
    .form-input:focus { outline: 2px solid var(--color-primary); border-color: transparent; }
    .form-select { appearance: none; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%23757575' d='M6 8L1 3h10z'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-position: right 1rem center; }
    .form-row { display: grid; grid-template-columns: 1fr 1fr; gap: var(--spacing-4); }
    .form-actions { display: flex; gap: var(--spacing-3); justify-content: flex-end; margin-top: var(--spacing-6); }

    /* ========== CHIPS ========== */
    .chip {
      display: inline-flex; align-items: center; gap: var(--spacing-2);
      padding: var(--spacing-1, 0.25rem) var(--spacing-3);
      border-radius: 9999px; font-size: 0.75rem; font-weight: 500;
    }
    .chip-success { background: #e8f5e9; color: #2e7d32; }
    .chip-warning { background: #fff3e0; color: #e65100; }
    .chip-error { background: #ffebee; color: #c62828; }

    /* ========== GRID LAYOUT ========== */
    .grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: var(--spacing-6); }
    @media (max-width: 768px) { .grid-2 { grid-template-columns: 1fr; } }
  </style>
</head>
<body>
  <button class="theme-toggle" onclick="document.body.classList.toggle('dark-theme')">
    <span class="material-icons" style="vertical-align: middle;">dark_mode</span> Toggle Dark Mode
  </button>

  <div class="container">
    <h1>Theme Preview: [Theme Name]</h1>

    <!-- ========== IMMER INKLUDIERT ========== -->

    <!-- COLOR PALETTE (immer) -->
    <h2>Farbpalette</h2>
    <div class="swatches">
      <div class="swatch" style="background: var(--color-primary);">
        <span class="swatch-label">Primary</span>
        <span class="swatch-hex">[primary-hex]</span>
      </div>
      <div class="swatch" style="background: var(--color-primary-light);">
        <span class="swatch-label">Primary Light</span>
        <span class="swatch-hex">[primary-light-hex]</span>
      </div>
      <div class="swatch" style="background: var(--color-primary-dark);">
        <span class="swatch-label">Primary Dark</span>
        <span class="swatch-hex">[primary-dark-hex]</span>
      </div>
      <div class="swatch" style="background: var(--color-accent);">
        <span class="swatch-label">Accent</span>
        <span class="swatch-hex">[accent-hex]</span>
      </div>
      <div class="swatch" style="background: var(--color-success);">
        <span class="swatch-label">Success</span>
        <span class="swatch-hex">#4caf50</span>
      </div>
      <div class="swatch" style="background: var(--color-warning);">
        <span class="swatch-label">Warning</span>
        <span class="swatch-hex">#ff9800</span>
      </div>
      <div class="swatch" style="background: var(--color-error);">
        <span class="swatch-label">Error</span>
        <span class="swatch-hex">#f44336</span>
      </div>
      <div class="swatch" style="background: var(--color-info);">
        <span class="swatch-label">Info</span>
        <span class="swatch-hex">#2196f3</span>
      </div>
    </div>

    <!-- TYPOGRAPHY (immer) -->
    <h2>Typografie</h2>
    <div class="card">
      <h1 style="margin-bottom: 0.5rem;">Heading 1 - Light 2.25rem</h1>
      <h2 style="margin: 0.5rem 0;">Heading 2 - Regular 1.5rem</h2>
      <h3 style="margin: 0.5rem 0;">Heading 3 - Medium 1.25rem</h3>
      <p style="margin-top: 1rem;">Body Text - Dies ist ein Beispieltext in der Standardschriftgröße. Die Schriftfamilie ist <strong>[theme-font]</strong>.</p>
      <p style="font-size: 0.875rem; color: var(--color-text-secondary); margin-top: 0.5rem;">Secondary Text - Kleinere Schrift für weniger wichtige Informationen.</p>
    </div>

    <!-- ========== BEDINGT: NUR WENN KOMPONENTE GEFUNDEN ========== -->

    <div class="grid-2">
      <!-- MINI TABLE (wenn mat-table ODER <table> gefunden) -->
      <div>
        <h2>Datentabelle</h2>
        <div class="card" style="padding: 0; overflow: hidden;">
          <table class="table">
            <thead>
              <tr>
                <th>Name</th>
                <th>Status</th>
                <th>Aktionen</th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td>Max Mustermann</td>
                <td><span class="chip chip-success">Aktiv</span></td>
                <td class="table-actions">
                  <button class="btn btn-icon btn-secondary"><span class="material-icons">edit</span></button>
                  <button class="btn btn-icon btn-danger"><span class="material-icons">delete</span></button>
                </td>
              </tr>
              <tr>
                <td>Erika Musterfrau</td>
                <td><span class="chip chip-warning">Ausstehend</span></td>
                <td class="table-actions">
                  <button class="btn btn-icon btn-secondary"><span class="material-icons">edit</span></button>
                  <button class="btn btn-icon btn-danger"><span class="material-icons">delete</span></button>
                </td>
              </tr>
              <tr>
                <td>John Doe</td>
                <td><span class="chip chip-error">Inaktiv</span></td>
                <td class="table-actions">
                  <button class="btn btn-icon btn-secondary"><span class="material-icons">edit</span></button>
                  <button class="btn btn-icon btn-danger"><span class="material-icons">delete</span></button>
                </td>
              </tr>
            </tbody>
          </table>
        </div>
      </div>

      <!-- MINI FORM (wenn mat-form-field ODER <input>/<select> gefunden) -->
      <div>
        <h2>Formular</h2>
        <div class="card">
          <h3>Benutzer bearbeiten</h3>
          <form style="margin-top: var(--spacing-4);">
            <div class="form-row">
              <div class="form-group">
                <label class="form-label">Vorname</label>
                <input type="text" class="form-input" value="Max" />
              </div>
              <div class="form-group">
                <label class="form-label">Nachname</label>
                <input type="text" class="form-input" value="Mustermann" />
              </div>
            </div>
            <div class="form-group">
              <label class="form-label">E-Mail</label>
              <input type="email" class="form-input" value="max@example.com" />
            </div>
            <div class="form-group">
              <label class="form-label">Rolle</label>
              <select class="form-input form-select">
                <option>Administrator</option>
                <option selected>Benutzer</option>
                <option>Gast</option>
              </select>
            </div>
            <div class="form-actions">
              <button type="button" class="btn btn-secondary">Abbrechen</button>
              <button type="submit" class="btn btn-primary">
                <span class="material-icons">save</span> Speichern
              </button>
            </div>
          </form>
        </div>
      </div>
    </div>

    <!-- BUTTONS (wenn mat-button ODER <button> gefunden) -->
    <h2>Buttons</h2>
    <div class="card" style="display: flex; gap: var(--spacing-4); flex-wrap: wrap; align-items: center;">
      <button class="btn btn-primary"><span class="material-icons">add</span> Primary</button>
      <button class="btn btn-secondary">Secondary</button>
      <button class="btn btn-danger"><span class="material-icons">delete</span> Danger</button>
      <button class="btn btn-primary" disabled style="opacity: 0.5; cursor: not-allowed;">Disabled</button>
    </div>
  </div>
</body>
</html>

Nach Erstellung:

THEME PREVIEW ERSTELLT: [Theme Name]

Öffnen Sie die Vorschau im Browser:
  open wireframes/theme-preview-[theme-name].html

Features:
- [X] Farbpalette mit allen Brand & Semantic Colors (immer)
- [X] Typografie-Beispiele (immer)
- [X] Dark Mode Toggle (immer)
- Projekt-spezifische Elemente (nur wenn im Projekt gefunden):
  - [ ] Datentabelle (mat-table ODER <table>)
  - [ ] Formular (mat-form-field ODER <input>/<select>)
  - [ ] Buttons (mat-button ODER <button>)
  - [ ] Listen (<ul>/<ol>)
  - [ ] Navigation (<nav>)
  - [ ] Cards, Chips, Dialogs, etc.

Nächste Schritte:
- Anderes Theme testen? → /byt8:ui-theming (Option 3)
- Dieses Theme übernehmen? → /byt8:ui-theming (Option 2 mit gleichem Theme)

Output

DESIGN SYSTEM INITIALIZED

Theme: [Selected Theme]
Primary: [primary-hex]
Accent: [accent-hex]
Font: [theme-font]

Files Created:
- [X] frontend/src/styles/tokens/_colors.scss
- [X] frontend/src/styles/tokens/_typography.scss
- [X] frontend/src/styles/tokens/_spacing.scss
- [X] frontend/src/styles/tokens/_elevation.scss
- [X] frontend/src/styles/tokens/_breakpoints.scss
- [X] frontend/src/styles/tokens/_index.scss
- [X] frontend/src/styles.scss (updated)
- [X] wireframes/theme-preview-[theme-name].html (Preview)

Architecture:
- CSS Custom Properties (runtime theming)
- @use/@forward module system (no @import)
- Light/Dark mode support
- 8pt spacing grid with semantic aliases
- Material Design elevations
- Responsive breakpoint mixins

Preview:
  open wireframes/theme-preview-[theme-name].html

Next Steps:
1. Preview öffnen und Theme prüfen (Light + Dark Mode)
2. Falls Theme nicht passt: /byt8:ui-theming erneut ausführen
3. Falls Theme passt: /byt8:full-stack-feature starten
4. In Components: var(--token-name) verwenden

When to Run

  • ONCE at project start
  • When changing the project theme
  • When updating design system tokens

Prerequisites

  • Frontend project initialized (npm install complete)
Stats
Parent Repo Stars0
Parent Repo Forks0
Last CommitFeb 2, 2026