Files
ui-essentials/HCL_STUDIO_USAGE_GUIDE.md
2025-09-12 15:23:58 +10:00

29 KiB

HCL Studio Usage Guide

🎨 Advanced Color Management with HCL Studio

HCL Studio is a sophisticated Angular library for perceptually uniform color palette generation using the HCL (Hue, Chroma, Lightness) color space. It creates Material Design 3 compliant themes with proper contrast ratios and accessibility support.


📋 What is HCL Studio?

HCL (Hue, Chroma, Lightness) is a perceptually uniform color space, meaning equal changes in values produce equal visual differences. Unlike RGB or HSL, HCL provides:

  • Perceptual uniformity - Linear changes appear visually consistent
  • Better contrast control - Precise lightness adjustments
  • Accessibility compliance - WCAG-compliant contrast ratios
  • Material Design 3 - Full tonal palette generation

🚀 Quick Start

1. Add HCL Studio to Your Project

# Add as submodule (recommended)
git submodule add https://git.sky-ai.com/jules/hcl-studio.git libs/hcl-studio

# Build the library
cd libs/hcl-studio && npm install && npm run build

2. Configure TypeScript Paths

In tsconfig.json:

{
  "compilerOptions": {
    "paths": {
      "hcl-studio": ["./libs/hcl-studio/dist"],
      "hcl-studio/*": ["./libs/hcl-studio/dist/*"]
    }
  }
}

3. Basic Usage

// app.component.ts
import { Component, OnInit } from '@angular/core';
import { HCLStudioService } from 'hcl-studio';

@Component({
  selector: 'app-root',
  template: `
    <div class="app">
      <button (click)="switchTheme()">Switch Theme</button>
      <div class="content">
        <h1>HCL Studio Demo</h1>
        <p>Dynamic theming with perceptually uniform colors!</p>
      </div>
    </div>
  `
})
export class AppComponent implements OnInit {
  
  constructor(private hclStudio: HCLStudioService) {}

  ngOnInit() {
    // Initialize with default theme
    this.hclStudio.initialize({
      defaultTheme: 'material-purple',
      autoMode: true // Automatically switch based on system preference
    });
  }

  switchTheme() {
    // Switch between built-in themes
    this.hclStudio.switchTheme('material-blue');
  }
}

🎯 Core Concepts

1. HCL Color Space

import { HCLConverter } from 'hcl-studio';

// Convert between color formats
const hcl = HCLConverter.hexToHcl('#6750A4');
console.log(hcl); // { h: 264, c: 48, l: 41 }

const rgb = HCLConverter.hclToRgb(hcl);
const hex = HCLConverter.hclToHex(hcl);

2. Tonal Palettes

import { PaletteGenerator } from 'hcl-studio';

// Generate complete tonal palette from seed color
const palette = PaletteGenerator.generateTonalPalette('#6750A4');

console.log(palette);
// {
//   0: '#000000',      // Pure black
//   10: '#21005D',     // Very dark
//   20: '#381E72',     // Dark
//   30: '#4F378B',     // Medium dark
//   40: '#6750A4',     // Base color
//   50: '#7F67BE',     // Medium
//   60: '#9A82DB',     // Medium light
//   70: '#B69DF8',     // Light
//   80: '#D0BCFF',     // Very light
//   90: '#EADDFF',     // Nearly white
//   95: '#F6EDFF',     // Almost white
//   99: '#FFFBFE',     // Near white
//   100: '#FFFFFF'     // Pure white
// }

3. Material Design 3 Palettes

import { PaletteGenerator, BrandColors } from 'hcl-studio';

// Define brand colors
const brandColors: BrandColors = {
  primary: '#6750A4',
  secondary: '#625B71', 
  tertiary: '#7D5260'
};

// Generate complete Material Design 3 palette
const materialPalette = PaletteGenerator.generateMaterialPalette(brandColors);

console.log(materialPalette);
// {
//   primary: { 0: '#000000', 10: '#21005D', ... },
//   secondary: { 0: '#000000', 10: '#1D1B20', ... },
//   tertiary: { 0: '#000000', 10: '#31111D', ... },
//   neutral: { 0: '#000000', 10: '#1D1B20', ... },
//   neutralVariant: { 0: '#000000', 10: '#1D1B20', ... },
//   error: { 0: '#000000', 10: '#410E0B', ... }
// }

🛠️ Service Usage

1. Initialize HCL Studio Service

import { Component, OnInit } from '@angular/core';
import { HCLStudioService, ThemeState } from 'hcl-studio';
import { Observable } from 'rxjs';

@Component({
  selector: 'app-theme-manager',
  template: `
    <div class="theme-manager">
      <h3>Theme Manager</h3>
      
      <!-- Theme Selector -->
      <select (change)="switchTheme($event.target.value)">
        <option *ngFor="let theme of (themeState$ | async)?.availableThemes" 
                [value]="theme.id">
          {{ theme.name }}
        </option>
      </select>
      
      <!-- Mode Toggle -->
      <button (click)="toggleMode()">
        {{ (currentMode$ | async) === 'light' ? '🌙' : '☀️' }}
        {{ (currentMode$ | async) === 'light' ? 'Dark' : 'Light' }} Mode
      </button>
      
      <!-- Current Theme Info -->
      <div *ngIf="themeState$ | async as state" class="theme-info">
        <h4>Current Theme: {{ state.currentTheme?.config.name }}</h4>
        <div class="color-preview">
          <div class="color-swatch" 
               [style.background-color]="state.currentTheme?.config.colors.primary">
          </div>
          <div class="color-swatch" 
               [style.background-color]="state.currentTheme?.config.colors.secondary">
          </div>
          <div class="color-swatch" 
               [style.background-color]="state.currentTheme?.config.colors.tertiary">
          </div>
        </div>
      </div>
    </div>
  `,
  styles: [`
    .theme-manager {
      padding: 2rem;
      background: var(--md-sys-color-surface-variant, #f5f5f5);
      border-radius: 12px;
      margin: 1rem;
    }
    
    .color-preview {
      display: flex;
      gap: 0.5rem;
      margin-top: 1rem;
    }
    
    .color-swatch {
      width: 40px;
      height: 40px;
      border-radius: 8px;
      border: 2px solid var(--md-sys-color-outline, #ccc);
    }
  `]
})
export class ThemeManagerComponent implements OnInit {
  
  themeState$: Observable<ThemeState>;
  currentMode$: Observable<'light' | 'dark'>;

  constructor(private hclStudio: HCLStudioService) {
    this.themeState$ = this.hclStudio.themeState$;
    this.currentMode$ = this.hclStudio.currentMode$;
  }

  async ngOnInit() {
    // Initialize with custom options
    await this.hclStudio.initialize({
      defaultTheme: 'material-purple',
      autoMode: true,
      storageKey: 'my-app-theme',
      validation: {
        enableContrastCheck: true,
        enableColorBlindCheck: true,
        minContrastRatio: 4.5
      }
    });
  }

  switchTheme(themeId: string) {
    this.hclStudio.switchTheme(themeId);
  }

  toggleMode() {
    this.hclStudio.toggleMode();
  }
}

2. Create Custom Themes

import { Component } from '@angular/core';
import { HCLStudioService, ThemeConfig } from 'hcl-studio';

@Component({
  selector: 'app-custom-theme-creator',
  template: `
    <div class="theme-creator">
      <h3>Create Custom Theme</h3>
      
      <form (submit)="createTheme()">
        <div class="form-group">
          <label>Theme Name</label>
          <input [(ngModel)]="customTheme.name" required>
        </div>
        
        <div class="form-group">
          <label>Primary Color</label>
          <input type="color" [(ngModel)]="customTheme.colors.primary">
        </div>
        
        <div class="form-group">
          <label>Secondary Color</label>
          <input type="color" [(ngModel)]="customTheme.colors.secondary">
        </div>
        
        <div class="form-group">
          <label>Tertiary Color</label>
          <input type="color" [(ngModel)]="customTheme.colors.tertiary">
        </div>
        
        <button type="submit">Create & Apply Theme</button>
      </form>
      
      <!-- Live Preview -->
      <div class="preview" [style.background-color]="customTheme.colors.primary">
        <h4 [style.color]="getContrastColor(customTheme.colors.primary)">
          {{ customTheme.name || 'Custom Theme' }}
        </h4>
        <button [style.background-color]="customTheme.colors.secondary">
          Secondary Action
        </button>
        <button [style.background-color]="customTheme.colors.tertiary">
          Tertiary Action
        </button>
      </div>
    </div>
  `
})
export class CustomThemeCreatorComponent {
  
  customTheme: ThemeConfig = {
    id: '',
    name: '',
    colors: {
      primary: '#6750A4',
      secondary: '#625B71',
      tertiary: '#7D5260'
    }
  };

  constructor(private hclStudio: HCLStudioService) {}

  async createTheme() {
    // Generate unique ID
    this.customTheme.id = `custom-${Date.now()}`;
    
    // Create and apply the theme
    const theme = await this.hclStudio.createCustomTheme(this.customTheme);
    await this.hclStudio.switchTheme(theme.config.id);
    
    console.log('Custom theme created:', theme);
  }
  
  getContrastColor(backgroundColor: string): string {
    // Simple contrast calculation
    const hex = backgroundColor.replace('#', '');
    const r = parseInt(hex.substr(0, 2), 16);
    const g = parseInt(hex.substr(2, 2), 16);
    const b = parseInt(hex.substr(4, 2), 16);
    const brightness = (r * 299 + g * 587 + b * 114) / 1000;
    return brightness > 128 ? '#000000' : '#ffffff';
  }
}

🎨 Advanced Features

1. Color Validation & Accessibility

import { HCLStudioService, ColorValidation } from 'hcl-studio';

@Component({
  selector: 'app-color-validator',
  template: `
    <div class="validator">
      <h3>Color Accessibility Validator</h3>
      
      <div class="color-inputs">
        <input type="color" [(ngModel)]="foregroundColor" (change)="validateColors()">
        <input type="color" [(ngModel)]="backgroundColor" (change)="validateColors()">
      </div>
      
      <div *ngIf="validation" class="validation-results">
        <div [class]="validation.isValid ? 'valid' : 'invalid'">
          {{ validation.isValid ? '✅' : '❌' }} 
          {{ validation.isValid ? 'Accessible' : 'Not Accessible' }}
        </div>
        
        <div class="contrast-info">
          Contrast Ratio: {{ validation.accessibility?.contrastRatio.toFixed(2) }}:1
          ({{ validation.accessibility?.wcagLevel }})
        </div>
        
        <div class="warnings" *ngIf="validation.warnings.length">
          <h4>Warnings:</h4>
          <ul>
            <li *ngFor="let warning of validation.warnings">{{ warning }}</li>
          </ul>
        </div>
        
        <div class="recommendations" *ngIf="validation.recommendations">
          <h4>Recommendations:</h4>
          <ul>
            <li *ngFor="let rec of validation.recommendations">{{ rec }}</li>
          </ul>
        </div>
      </div>
    </div>
  `
})
export class ColorValidatorComponent {
  
  foregroundColor = '#000000';
  backgroundColor = '#ffffff';
  validation: ColorValidation | null = null;

  constructor(private hclStudio: HCLStudioService) {}

  validateColors() {
    this.validation = this.hclStudio.validateColorCombination(
      this.foregroundColor,
      this.backgroundColor
    );
  }
}

2. Dynamic Theme Switching with Animations

import { Component } from '@angular/core';
import { HCLStudioService } from 'hcl-studio';

@Component({
  selector: 'app-animated-theme-switcher',
  template: `
    <div class="theme-switcher" [class.switching]="isSwitching">
      <div class="theme-grid">
        <div *ngFor="let theme of availableThemes" 
             class="theme-card"
             (click)="switchToTheme(theme.id)"
             [class.active]="theme.id === currentThemeId">
          
          <div class="theme-preview">
            <div class="color-bar" [style.background-color]="theme.primary"></div>
            <div class="color-bar" [style.background-color]="theme.secondary"></div>
            <div class="color-bar" [style.background-color]="theme.tertiary"></div>
          </div>
          
          <h4>{{ theme.name }}</h4>
          <p>{{ theme.description }}</p>
        </div>
      </div>
    </div>
  `,
  styles: [`
    .theme-switcher {
      padding: 2rem;
      transition: opacity 0.3s ease;
    }
    
    .theme-switcher.switching {
      opacity: 0.7;
    }
    
    .theme-grid {
      display: grid;
      grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
      gap: 1.5rem;
    }
    
    .theme-card {
      background: var(--md-sys-color-surface-variant);
      border-radius: 12px;
      padding: 1.5rem;
      cursor: pointer;
      transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
      border: 2px solid transparent;
    }
    
    .theme-card:hover {
      transform: translateY(-4px);
      box-shadow: 0 8px 32px rgba(0,0,0,0.1);
    }
    
    .theme-card.active {
      border-color: var(--md-sys-color-primary);
      background: var(--md-sys-color-primary-container);
    }
    
    .theme-preview {
      display: flex;
      height: 40px;
      border-radius: 8px;
      overflow: hidden;
      margin-bottom: 1rem;
    }
    
    .color-bar {
      flex: 1;
    }
    
    @keyframes themeTransition {
      0% { opacity: 1; }
      50% { opacity: 0.5; }
      100% { opacity: 1; }
    }
    
    .switching {
      animation: themeTransition 0.6s ease-in-out;
    }
  `]
})
export class AnimatedThemeSwitcherComponent implements OnInit {
  
  availableThemes: any[] = [];
  currentThemeId: string = '';
  isSwitching = false;

  constructor(private hclStudio: HCLStudioService) {}

  ngOnInit() {
    // Subscribe to theme state
    this.hclStudio.themeState$.subscribe(state => {
      this.availableThemes = state.availableThemes;
      this.currentThemeId = state.currentTheme?.config.id || '';
    });
  }

  async switchToTheme(themeId: string) {
    if (this.currentThemeId === themeId) return;
    
    this.isSwitching = true;
    
    // Add delay for animation
    setTimeout(async () => {
      await this.hclStudio.switchTheme(themeId);
      this.isSwitching = false;
    }, 300);
  }
}

3. CSS Variable Integration

import { Component, OnInit } from '@angular/core';
import { HCLStudioService, CSSVariableManager } from 'hcl-studio';

@Component({
  selector: 'app-css-variables-demo',
  template: `
    <div class="demo-container">
      <div class="surface-demo">
        <h2>Surface Containers</h2>
        <div class="surface-grid">
          <div class="surface-card surface-1">Surface 1</div>
          <div class="surface-card surface-2">Surface 2</div>
          <div class="surface-card surface-3">Surface 3</div>
          <div class="surface-card surface-4">Surface 4</div>
        </div>
      </div>
      
      <div class="color-roles-demo">
        <h2>Color Roles</h2>
        <div class="color-grid">
          <div class="color-example primary">Primary</div>
          <div class="color-example secondary">Secondary</div>
          <div class="color-example tertiary">Tertiary</div>
          <div class="color-example error">Error</div>
        </div>
      </div>
      
      <div class="text-demo">
        <h2>Text Hierarchy</h2>
        <div class="text-on-primary">Text on Primary</div>
        <div class="text-on-secondary">Text on Secondary</div>
        <div class="text-on-surface">Text on Surface</div>
        <div class="text-outline">Outline Text</div>
      </div>
    </div>
  `,
  styles: [`
    .demo-container {
      padding: 2rem;
      background: var(--md-sys-color-background);
      color: var(--md-sys-color-on-background);
      min-height: 100vh;
    }
    
    /* Surface Containers */
    .surface-grid {
      display: grid;
      grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
      gap: 1rem;
      margin: 1rem 0;
    }
    
    .surface-card {
      padding: 2rem;
      border-radius: var(--md-sys-shape-corner-medium, 12px);
      text-align: center;
      font-weight: 500;
    }
    
    .surface-1 {
      background: var(--md-sys-color-surface);
      color: var(--md-sys-color-on-surface);
    }
    
    .surface-2 {
      background: var(--md-sys-color-surface-variant);
      color: var(--md-sys-color-on-surface-variant);
    }
    
    .surface-3 {
      background: var(--md-sys-color-surface-container);
      color: var(--md-sys-color-on-surface);
    }
    
    .surface-4 {
      background: var(--md-sys-color-surface-container-high);
      color: var(--md-sys-color-on-surface);
    }
    
    /* Color Roles */
    .color-grid {
      display: flex;
      gap: 1rem;
      flex-wrap: wrap;
      margin: 1rem 0;
    }
    
    .color-example {
      padding: 1.5rem 2rem;
      border-radius: var(--md-sys-shape-corner-medium, 12px);
      font-weight: 600;
      text-align: center;
      min-width: 120px;
    }
    
    .primary {
      background: var(--md-sys-color-primary);
      color: var(--md-sys-color-on-primary);
    }
    
    .secondary {
      background: var(--md-sys-color-secondary);
      color: var(--md-sys-color-on-secondary);
    }
    
    .tertiary {
      background: var(--md-sys-color-tertiary);
      color: var(--md-sys-color-on-tertiary);
    }
    
    .error {
      background: var(--md-sys-color-error);
      color: var(--md-sys-color-on-error);
    }
    
    /* Text Examples */
    .text-demo > div {
      padding: 1rem;
      margin: 0.5rem 0;
      border-radius: 8px;
    }
    
    .text-on-primary {
      background: var(--md-sys-color-primary);
      color: var(--md-sys-color-on-primary);
    }
    
    .text-on-secondary {
      background: var(--md-sys-color-secondary);
      color: var(--md-sys-color-on-secondary);
    }
    
    .text-on-surface {
      background: var(--md-sys-color-surface);
      color: var(--md-sys-color-on-surface);
      border: 1px solid var(--md-sys-color-outline);
    }
    
    .text-outline {
      background: var(--md-sys-color-background);
      color: var(--md-sys-color-outline);
      border: 2px solid var(--md-sys-color-outline);
    }
  `]
})
export class CSSVariablesDemoComponent implements OnInit {

  constructor(private hclStudio: HCLStudioService) {}

  ngOnInit() {
    // The CSS variables are automatically applied by HCL Studio
    // They follow Material Design 3 token naming conventions
    console.log('CSS Variables Demo loaded');
    
    // You can also manually access the variable manager
    const cssVars = CSSVariableManager.getAllVariables();
    console.log('Current CSS variables:', cssVars);
  }
}

🎯 Built-in Themes

HCL Studio comes with professionally curated themes:

Material Design Themes

  • material-purple - Classic Material Design purple
  • material-blue - Professional blue theme
  • material-green - Nature-inspired green theme

Brand Themes

  • corporate-blue - Professional corporate theme
  • startup-orange - Energetic startup theme
  • fintech-navy - Trust-focused financial theme

Creative Themes

  • sunset-gradient - Warm sunset colors
  • ocean-breeze - Cool ocean-inspired palette
  • forest-earth - Natural earth tones

Usage:

// Switch to any built-in theme
await this.hclStudio.switchTheme('sunset-gradient');

🔧 Advanced Configuration

1. Custom Theme Presets

import { HCLStudioOptions, ThemeCollection } from 'hcl-studio';

const customThemes: ThemeCollection = {
  'my-brand': {
    name: 'My Brand Theme',
    description: 'Custom brand colors',
    colors: {
      primary: '#FF6B35',
      secondary: '#004E89', 
      tertiary: '#009639'
    }
  },
  'dark-mode-pro': {
    name: 'Dark Mode Pro',
    description: 'Professional dark theme',
    colors: {
      primary: '#BB86FC',
      secondary: '#03DAC6',
      tertiary: '#CF6679'
    }
  }
};

const options: HCLStudioOptions = {
  defaultTheme: 'my-brand',
  autoMode: true,
  themes: customThemes,
  validation: {
    enableContrastCheck: true,
    enableColorBlindCheck: true,
    minContrastRatio: 4.5
  }
};

await this.hclStudio.initialize(options);

2. Theme Persistence

// Themes are automatically saved to localStorage
// Customize the storage key:
await this.hclStudio.initialize({
  storageKey: 'my-app-theme-v2'
});

// Manually save/load themes
const themeStorage = new ThemeStorage('custom-key');
await themeStorage.saveTheme(myCustomTheme);
const savedThemes = await themeStorage.getAllThemes();

3. Color Harmony Generation

import { PaletteGenerator } from 'hcl-studio';

// Generate harmonious color schemes
const baseColor = '#6750A4';

const complementary = PaletteGenerator.generateHarmony(baseColor, 'complementary');
const analogous = PaletteGenerator.generateHarmony(baseColor, 'analogous');
const triadic = PaletteGenerator.generateHarmony(baseColor, 'triadic');

console.log('Complementary colors:', complementary);
// ['#6750A4', '#50A467'] - opposite hues

console.log('Analogous colors:', analogous);  
// ['#6750A4', '#8750A4', '#5067A4'] - adjacent hues

console.log('Triadic colors:', triadic);
// ['#6750A4', '#A46750', '#50A467'] - evenly spaced hues

🎨 Real-World Examples

1. E-commerce Theme System

@Component({
  selector: 'app-ecommerce-theme',
  template: `
    <div class="ecommerce-app">
      <!-- Brand Header -->
      <header class="brand-header">
        <h1>ShopSpace</h1>
        <div class="theme-selector">
          <button (click)="switchTheme('corporate-blue')">Professional</button>
          <button (click)="switchTheme('startup-orange')">Energetic</button>
          <button (click)="switchTheme('fintech-navy')">Trustworthy</button>
        </div>
      </header>
      
      <!-- Product Cards -->
      <main class="product-grid">
        <div *ngFor="let product of products" class="product-card">
          <img [src]="product.image" [alt]="product.name">
          <h3>{{ product.name }}</h3>
          <p class="price">\${{ product.price }}</p>
          <button class="add-to-cart">Add to Cart</button>
        </div>
      </main>
    </div>
  `,
  styles: [`
    .ecommerce-app {
      background: var(--md-sys-color-background);
      min-height: 100vh;
    }
    
    .brand-header {
      background: var(--md-sys-color-primary);
      color: var(--md-sys-color-on-primary);
      padding: 2rem;
      display: flex;
      justify-content: space-between;
      align-items: center;
    }
    
    .product-grid {
      display: grid;
      grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
      gap: 2rem;
      padding: 2rem;
    }
    
    .product-card {
      background: var(--md-sys-color-surface);
      color: var(--md-sys-color-on-surface);
      border-radius: var(--md-sys-shape-corner-large, 16px);
      padding: 1.5rem;
      box-shadow: var(--md-sys-elevation-1);
      transition: all 0.3s ease;
    }
    
    .product-card:hover {
      box-shadow: var(--md-sys-elevation-2);
      transform: translateY(-2px);
    }
    
    .add-to-cart {
      background: var(--md-sys-color-primary);
      color: var(--md-sys-color-on-primary);
      border: none;
      padding: 0.75rem 1.5rem;
      border-radius: var(--md-sys-shape-corner-medium, 12px);
      font-weight: 600;
      cursor: pointer;
      width: 100%;
      margin-top: 1rem;
    }
    
    .price {
      color: var(--md-sys-color-primary);
      font-size: 1.5rem;
      font-weight: 700;
    }
  `]
})
export class EcommerceThemeComponent {
  products = [
    { name: 'Premium Headphones', price: 299, image: '/assets/headphones.jpg' },
    { name: 'Smart Watch', price: 199, image: '/assets/watch.jpg' },
    // ... more products
  ];

  constructor(private hclStudio: HCLStudioService) {}

  switchTheme(themeId: string) {
    this.hclStudio.switchTheme(themeId);
  }
}

2. Dashboard Theme Manager

@Component({
  selector: 'app-dashboard-theme-manager', 
  template: `
    <div class="dashboard">
      <aside class="sidebar">
        <h3>Theme Controls</h3>
        
        <!-- Custom Color Picker -->
        <div class="color-controls">
          <label>Primary Color</label>
          <input type="color" 
                 [ngModel]="currentPrimary" 
                 (ngModelChange)="updatePrimaryColor($event)">
        </div>
        
        <!-- Preset Themes -->
        <div class="preset-themes">
          <h4>Preset Themes</h4>
          <div *ngFor="let theme of presetThemes" 
               class="theme-option"
               (click)="applyPreset(theme.id)">
            <div class="theme-colors">
              <span class="color-dot" [style.background-color]="theme.primary"></span>
              <span class="color-dot" [style.background-color]="theme.secondary"></span>
            </div>
            <span>{{ theme.name }}</span>
          </div>
        </div>
        
        <!-- Mode Toggle -->
        <button class="mode-toggle" (click)="toggleMode()">
          {{ currentMode === 'light' ? '🌙 Dark Mode' : '☀️ Light Mode' }}
        </button>
      </aside>
      
      <main class="main-content">
        <div class="dashboard-widgets">
          <div class="widget">
            <h3>Revenue</h3>
            <div class="metric">\$45,678</div>
          </div>
          <div class="widget">
            <h3>Users</h3>
            <div class="metric">12,345</div>
          </div>
          <div class="widget">
            <h3>Growth</h3>
            <div class="metric">+23%</div>
          </div>
        </div>
      </main>
    </div>
  `,
  styles: [`
    .dashboard {
      display: flex;
      height: 100vh;
      background: var(--md-sys-color-background);
    }
    
    .sidebar {
      width: 300px;
      background: var(--md-sys-color-surface);
      color: var(--md-sys-color-on-surface);
      padding: 2rem;
      border-right: 1px solid var(--md-sys-color-outline);
    }
    
    .main-content {
      flex: 1;
      padding: 2rem;
    }
    
    .dashboard-widgets {
      display: grid;
      grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
      gap: 2rem;
    }
    
    .widget {
      background: var(--md-sys-color-surface-variant);
      color: var(--md-sys-color-on-surface);
      padding: 2rem;
      border-radius: var(--md-sys-shape-corner-large, 16px);
      text-align: center;
    }
    
    .metric {
      font-size: 2.5rem;
      font-weight: 700;
      color: var(--md-sys-color-primary);
      margin-top: 1rem;
    }
    
    .theme-option {
      display: flex;
      align-items: center;
      gap: 1rem;
      padding: 0.75rem;
      border-radius: 8px;
      cursor: pointer;
      transition: background 0.2s;
    }
    
    .theme-option:hover {
      background: var(--md-sys-color-surface-variant);
    }
    
    .theme-colors {
      display: flex;
      gap: 0.5rem;
    }
    
    .color-dot {
      width: 16px;
      height: 16px;
      border-radius: 50%;
      border: 2px solid var(--md-sys-color-outline);
    }
    
    .mode-toggle {
      background: var(--md-sys-color-secondary);
      color: var(--md-sys-color-on-secondary);
      border: none;
      padding: 1rem;
      border-radius: var(--md-sys-shape-corner-medium, 12px);
      cursor: pointer;
      width: 100%;
      margin-top: 2rem;
      font-weight: 600;
    }
  `]
})
export class DashboardThemeManagerComponent implements OnInit {
  
  currentPrimary = '#6750A4';
  currentMode: 'light' | 'dark' = 'light';
  
  presetThemes = [
    { id: 'material-blue', name: 'Material Blue', primary: '#1976D2', secondary: '#455A64' },
    { id: 'corporate-blue', name: 'Corporate', primary: '#2E7D32', secondary: '#5D4037' },
    { id: 'startup-orange', name: 'Startup', primary: '#FF6B35', secondary: '#004E89' }
  ];

  constructor(private hclStudio: HCLStudioService) {}

  ngOnInit() {
    this.hclStudio.currentMode$.subscribe(mode => {
      this.currentMode = mode;
    });
  }

  updatePrimaryColor(color: string) {
    this.currentPrimary = color;
    
    // Create real-time custom theme
    const customTheme = {
      id: 'live-custom',
      name: 'Live Custom',
      colors: {
        primary: color,
        secondary: '#625B71',
        tertiary: '#7D5260'
      }
    };
    
    this.hclStudio.createCustomTheme(customTheme)
      .then(theme => this.hclStudio.switchTheme(theme.config.id));
  }

  applyPreset(themeId: string) {
    this.hclStudio.switchTheme(themeId);
  }

  toggleMode() {
    this.hclStudio.toggleMode();
  }
}

Best Practices

1. Initialize Early

// In AppComponent or app.config.ts
ngOnInit() {
  this.hclStudio.initialize({
    defaultTheme: 'material-purple',
    autoMode: true
  });
}

2. Use Reactive Patterns

// Subscribe to theme changes
this.hclStudio.themeState$.subscribe(state => {
  console.log('Theme changed:', state.currentTheme?.config.name);
});

3. Validate Color Combinations

const validation = this.hclStudio.validateColorCombination('#ffffff', '#f0f0f0');
if (!validation.isValid) {
  console.warn('Poor contrast ratio:', validation.warnings);
}

4. Performance Optimization

// Debounce rapid theme changes
const debouncedThemeChange = debounceTime(300);
this.colorPicker$.pipe(debouncedThemeChange)
  .subscribe(color => this.updateTheme(color));

🚀 You're Ready!

HCL Studio provides professional-grade color management with:

  • Perceptually uniform colors using HCL color space
  • Material Design 3 compliance with complete tonal palettes
  • Accessibility validation with WCAG contrast checking
  • Reactive theme management with RxJS observables
  • CSS custom properties integration
  • Theme persistence and storage
  • Color harmony generation for professional palettes

Create stunning, accessible, and professionally designed color systems for your Angular applications! 🎨