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

1137 lines
29 KiB
Markdown

# 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
```bash
# 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`:
```json
{
"compilerOptions": {
"paths": {
"hcl-studio": ["./libs/hcl-studio/dist"],
"hcl-studio/*": ["./libs/hcl-studio/dist/*"]
}
}
}
```
### 3. Basic Usage
```typescript
// 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**
```typescript
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**
```typescript
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**
```typescript
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**
```typescript
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**
```typescript
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**
```typescript
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**
```typescript
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**
```typescript
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:
```typescript
// Switch to any built-in theme
await this.hclStudio.switchTheme('sunset-gradient');
```
---
## 🔧 Advanced Configuration
### 1. **Custom Theme Presets**
```typescript
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**
```typescript
// 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**
```typescript
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**
```typescript
@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**
```typescript
@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**
```typescript
// In AppComponent or app.config.ts
ngOnInit() {
this.hclStudio.initialize({
defaultTheme: 'material-purple',
autoMode: true
});
}
```
### 2. **Use Reactive Patterns**
```typescript
// Subscribe to theme changes
this.hclStudio.themeState$.subscribe(state => {
console.log('Theme changed:', state.currentTheme?.config.name);
});
```
### 3. **Validate Color Combinations**
```typescript
const validation = this.hclStudio.validateColorCombination('#ffffff', '#f0f0f0');
if (!validation.isValid) {
console.warn('Poor contrast ratio:', validation.warnings);
}
```
### 4. **Performance Optimization**
```typescript
// 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! 🎨