Jules
This commit is contained in:
@@ -9,7 +9,9 @@
|
||||
"Bash(do)",
|
||||
"Bash(curl:*)",
|
||||
"Bash(echo:*)",
|
||||
"Bash(done)"
|
||||
"Bash(done)",
|
||||
"Bash(git commit:*)",
|
||||
"Bash(git push:*)"
|
||||
],
|
||||
"deny": [],
|
||||
"ask": []
|
||||
|
||||
978
CUSTOMIZATION_AND_THEMING_GUIDE.md
Normal file
978
CUSTOMIZATION_AND_THEMING_GUIDE.md
Normal file
@@ -0,0 +1,978 @@
|
||||
# SSuite Customization and Theming Guide
|
||||
|
||||
## 🎨 Complete Guide to Styling and Overriding SSuite Libraries
|
||||
|
||||
This guide shows you how to customize and theme your Angular project using the SSuite library ecosystem. Learn how to override colors, typography, components, and create your own design system on top of the foundation.
|
||||
|
||||
---
|
||||
|
||||
## 📋 Prerequisites
|
||||
|
||||
Before customizing, ensure you have:
|
||||
- **SSuite libraries integrated** (follow `CONSUMER_INTEGRATION_GUIDE.md`)
|
||||
- **ui-design-system** added as a submodule (foundation library)
|
||||
- **Basic SCSS knowledge** for advanced customizations
|
||||
|
||||
---
|
||||
|
||||
## 🏗️ Customization Architecture
|
||||
|
||||
SSuite uses a **layered architecture** for maximum flexibility:
|
||||
|
||||
```
|
||||
Your Custom Theme
|
||||
↓
|
||||
Semantic Tokens ← Override here for colors, typography, spacing
|
||||
↓
|
||||
Base Tokens ← Override here for foundational values
|
||||
↓
|
||||
Components ← Override here for specific component styling
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Approach 1: CSS Custom Properties (Recommended)
|
||||
|
||||
The easiest way to customize SSuite libraries using CSS variables.
|
||||
|
||||
### 1. Create Your Theme File
|
||||
|
||||
Create `src/styles/theme.scss`:
|
||||
|
||||
```scss
|
||||
// ==========================================================================
|
||||
// YOUR CUSTOM THEME
|
||||
// ==========================================================================
|
||||
|
||||
// Import design system first
|
||||
@use 'ui-design-system/src/styles' as ui;
|
||||
|
||||
// ==========================================================================
|
||||
// 🎨 COLOR OVERRIDES
|
||||
// ==========================================================================
|
||||
|
||||
:root {
|
||||
// Primary Brand Colors
|
||||
--color-primary: #6366f1; // Your brand primary (indigo)
|
||||
--color-secondary: #8b5cf6; // Your brand secondary (purple)
|
||||
--color-tertiary: #10b981; // Your accent color (emerald)
|
||||
--color-error: #ef4444; // Error/danger color (red)
|
||||
|
||||
// Primary color variations
|
||||
--color-primary-50: #eef2ff;
|
||||
--color-primary-100: #e0e7ff;
|
||||
--color-primary-500: #6366f1; // Main primary
|
||||
--color-primary-600: #4f46e5;
|
||||
--color-primary-700: #4338ca;
|
||||
--color-primary-900: #312e81;
|
||||
|
||||
// Surface colors (backgrounds)
|
||||
--color-surface: #ffffff;
|
||||
--color-surface-variant: #f8fafc;
|
||||
--color-surface-container: #f1f5f9;
|
||||
--color-surface-dim: #e2e8f0;
|
||||
|
||||
// Text colors on your custom colors
|
||||
--color-on-primary: #ffffff;
|
||||
--color-on-secondary: #ffffff;
|
||||
--color-on-surface: #1e293b;
|
||||
|
||||
// ==========================================================================
|
||||
// ✍️ TYPOGRAPHY OVERRIDES
|
||||
// ==========================================================================
|
||||
|
||||
// Font families (use your own fonts)
|
||||
--font-family-sans: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
|
||||
--font-family-mono: 'JetBrains Mono', 'Fira Code', monospace;
|
||||
--font-family-display: 'Playfair Display', Georgia, serif;
|
||||
|
||||
// Font sizes
|
||||
--font-size-xs: 0.75rem; // 12px
|
||||
--font-size-sm: 0.875rem; // 14px
|
||||
--font-size-base: 1rem; // 16px
|
||||
--font-size-lg: 1.125rem; // 18px
|
||||
--font-size-xl: 1.25rem; // 20px
|
||||
--font-size-2xl: 1.5rem; // 24px
|
||||
--font-size-3xl: 1.875rem; // 30px
|
||||
--font-size-4xl: 2.25rem; // 36px
|
||||
|
||||
// ==========================================================================
|
||||
// 📏 SPACING & SIZING OVERRIDES
|
||||
// ==========================================================================
|
||||
|
||||
// Border radius (adjust roundness)
|
||||
--border-radius-sm: 0.25rem; // 4px - subtle
|
||||
--border-radius-base: 0.5rem; // 8px - default
|
||||
--border-radius-lg: 0.75rem; // 12px - rounded
|
||||
--border-radius-xl: 1rem; // 16px - very rounded
|
||||
|
||||
// Component-specific spacing
|
||||
--spacing-button-padding-x: 1.5rem; // Button horizontal padding
|
||||
--spacing-button-padding-y: 0.75rem; // Button vertical padding
|
||||
--spacing-card-padding: 1.5rem; // Card interior padding
|
||||
--spacing-section: 4rem; // Section spacing
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Import Your Theme
|
||||
|
||||
In `src/styles.scss`:
|
||||
|
||||
```scss
|
||||
// Import your custom theme (this sets CSS variables)
|
||||
@import 'styles/theme';
|
||||
|
||||
// Global styles using your theme
|
||||
body {
|
||||
font-family: var(--font-family-sans);
|
||||
background-color: var(--color-surface);
|
||||
color: var(--color-on-surface);
|
||||
}
|
||||
|
||||
// Apply theme to headings
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
font-family: var(--font-family-display);
|
||||
color: var(--color-primary);
|
||||
}
|
||||
|
||||
// Custom link styling
|
||||
a {
|
||||
color: var(--color-primary);
|
||||
|
||||
&:hover {
|
||||
color: var(--color-primary-600);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Approach 2: SCSS Variable Overrides (Advanced)
|
||||
|
||||
For deeper customization, override SCSS variables before importing SSuite.
|
||||
|
||||
### 1. Create Advanced Theme File
|
||||
|
||||
Create `src/styles/advanced-theme.scss`:
|
||||
|
||||
```scss
|
||||
// ==========================================================================
|
||||
// ADVANCED SCSS VARIABLE OVERRIDES
|
||||
// ==========================================================================
|
||||
|
||||
// ==========================================================================
|
||||
// 🎨 COLOR VARIABLE OVERRIDES (before importing ui-design-system)
|
||||
// ==========================================================================
|
||||
|
||||
// Override semantic colors
|
||||
$semantic-color-brand-primary: #7c3aed !default; // Purple brand
|
||||
$semantic-color-brand-secondary: #059669 !default; // Emerald secondary
|
||||
$semantic-color-brand-accent: #dc2626 !default; // Red accent
|
||||
|
||||
// Override feedback colors
|
||||
$semantic-color-success: #10b981 !default; // Custom green
|
||||
$semantic-color-warning: #f59e0b !default; // Custom amber
|
||||
$semantic-color-danger: #ef4444 !default; // Custom red
|
||||
$semantic-color-info: #3b82f6 !default; // Custom blue
|
||||
|
||||
// Override surface colors
|
||||
$semantic-color-surface-primary: #ffffff !default; // Pure white
|
||||
$semantic-color-surface-secondary: #f9fafb !default; // Off-white
|
||||
$semantic-color-surface-elevated: #f3f4f6 !default; // Light gray
|
||||
|
||||
// ==========================================================================
|
||||
// ✍️ TYPOGRAPHY VARIABLE OVERRIDES
|
||||
// ==========================================================================
|
||||
|
||||
// Font families
|
||||
$base-typography-font-family-sans: 'Inter', sans-serif !default;
|
||||
$base-typography-font-family-mono: 'JetBrains Mono', monospace !default;
|
||||
$base-typography-font-family-display: 'Playfair Display', serif !default;
|
||||
|
||||
// Font sizes
|
||||
$base-typography-font-size-xs: 0.75rem !default; // 12px
|
||||
$base-typography-font-size-sm: 0.875rem !default; // 14px
|
||||
$base-typography-font-size-base: 1rem !default; // 16px
|
||||
$base-typography-font-size-lg: 1.125rem !default; // 18px
|
||||
$base-typography-font-size-xl: 1.25rem !default; // 20px
|
||||
$base-typography-font-size-2xl: 1.5rem !default; // 24px
|
||||
$base-typography-font-size-3xl: 1.875rem !default; // 30px
|
||||
$base-typography-font-size-4xl: 2.25rem !default; // 36px
|
||||
|
||||
// Line heights
|
||||
$base-typography-line-height-tight: 1.25 !default;
|
||||
$base-typography-line-height-snug: 1.375 !default;
|
||||
$base-typography-line-height-normal: 1.5 !default;
|
||||
$base-typography-line-height-relaxed: 1.625 !default;
|
||||
|
||||
// ==========================================================================
|
||||
// 📏 SPACING & LAYOUT OVERRIDES
|
||||
// ==========================================================================
|
||||
|
||||
// Border radius
|
||||
$semantic-border-button-radius: 0.75rem !default; // Rounded buttons
|
||||
$semantic-border-card-radius: 1rem !default; // Very rounded cards
|
||||
$semantic-border-input-radius: 0.5rem !default; // Moderate inputs
|
||||
|
||||
// Spacing values
|
||||
$semantic-spacing-section-padding: 5rem !default; // Generous sections
|
||||
$semantic-spacing-card-padding: 2rem !default; // Spacious cards
|
||||
$semantic-spacing-interactive-button-padding-x: 2rem !default; // Wide buttons
|
||||
$semantic-spacing-interactive-button-padding-y: 0.875rem !default; // Tall buttons
|
||||
|
||||
// NOW import ui-design-system (it will use your overridden variables)
|
||||
@use 'ui-design-system/src/styles' as ui;
|
||||
```
|
||||
|
||||
### 2. Use Advanced Theme
|
||||
|
||||
In `src/styles.scss`:
|
||||
|
||||
```scss
|
||||
// Import your advanced theme
|
||||
@import 'styles/advanced-theme';
|
||||
|
||||
// Global styles
|
||||
body {
|
||||
font-family: ui.$base-typography-font-family-sans;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
// Custom component styles
|
||||
.custom-hero {
|
||||
background: linear-gradient(
|
||||
45deg,
|
||||
var(--color-primary),
|
||||
var(--color-secondary)
|
||||
);
|
||||
color: white;
|
||||
padding: var(--spacing-section);
|
||||
border-radius: var(--border-radius-lg);
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Approach 3: Component-Specific Overrides
|
||||
|
||||
Target specific SSuite components for surgical customizations.
|
||||
|
||||
### 1. Override Button Components
|
||||
|
||||
Create `src/styles/component-overrides.scss`:
|
||||
|
||||
```scss
|
||||
// ==========================================================================
|
||||
// COMPONENT-SPECIFIC OVERRIDES
|
||||
// ==========================================================================
|
||||
@use 'ui-design-system/src/styles' as ui;
|
||||
|
||||
// ==========================================================================
|
||||
// 🔘 BUTTON OVERRIDES
|
||||
// ==========================================================================
|
||||
|
||||
// Override all buttons
|
||||
ui-button, .ui-button {
|
||||
// Custom button base
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.5px;
|
||||
box-shadow: 0 4px 14px 0 rgba(0, 0, 0, 0.1);
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
|
||||
// Custom hover effects
|
||||
&:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 8px 25px 0 rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
&:active {
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
// Primary button overrides
|
||||
ui-button[variant="primary"], .ui-button--primary {
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
border: none;
|
||||
|
||||
&:hover {
|
||||
background: linear-gradient(135deg, #5a6fd8 0%, #6a4190 100%);
|
||||
}
|
||||
}
|
||||
|
||||
// Secondary button overrides
|
||||
ui-button[variant="secondary"], .ui-button--secondary {
|
||||
background: transparent;
|
||||
border: 2px solid var(--color-primary);
|
||||
color: var(--color-primary);
|
||||
|
||||
&:hover {
|
||||
background: var(--color-primary);
|
||||
color: var(--color-on-primary);
|
||||
}
|
||||
}
|
||||
|
||||
// Outline button overrides
|
||||
ui-button[variant="outline"], .ui-button--outline {
|
||||
border: 2px solid currentColor;
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
backdrop-filter: blur(10px);
|
||||
}
|
||||
|
||||
// ==========================================================================
|
||||
// 📋 FORM OVERRIDES
|
||||
// ==========================================================================
|
||||
|
||||
// Input field overrides
|
||||
ui-text-input, .ui-text-input {
|
||||
input {
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
border: 2px solid transparent;
|
||||
border-radius: var(--border-radius-lg);
|
||||
padding: 1rem 1.25rem;
|
||||
font-size: var(--font-size-base);
|
||||
transition: all 0.2s ease;
|
||||
|
||||
&:focus {
|
||||
background: rgba(255, 255, 255, 1);
|
||||
border-color: var(--color-primary);
|
||||
box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.1);
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Form field overrides
|
||||
ui-form-field, .ui-form-field {
|
||||
.field-label {
|
||||
font-weight: 600;
|
||||
color: var(--color-primary);
|
||||
margin-bottom: 0.75rem;
|
||||
}
|
||||
|
||||
.field-error {
|
||||
color: var(--color-danger);
|
||||
font-size: var(--font-size-sm);
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
// ==========================================================================
|
||||
// 🃏 CARD OVERRIDES
|
||||
// ==========================================================================
|
||||
|
||||
ui-card, .ui-card {
|
||||
background: rgba(255, 255, 255, 0.95);
|
||||
backdrop-filter: blur(20px);
|
||||
border: 1px solid rgba(255, 255, 255, 0.2);
|
||||
border-radius: var(--border-radius-xl);
|
||||
box-shadow:
|
||||
0 8px 32px rgba(31, 38, 135, 0.37),
|
||||
0 4px 16px rgba(31, 38, 135, 0.2);
|
||||
transition: all 0.3s ease;
|
||||
|
||||
&:hover {
|
||||
transform: translateY(-4px);
|
||||
box-shadow:
|
||||
0 16px 64px rgba(31, 38, 135, 0.4),
|
||||
0 8px 32px rgba(31, 38, 135, 0.25);
|
||||
}
|
||||
}
|
||||
|
||||
// ==========================================================================
|
||||
// 🚀 LANDING PAGE OVERRIDES
|
||||
// ==========================================================================
|
||||
|
||||
// Hero section overrides
|
||||
ui-hero-section, .ui-hero-section {
|
||||
background: linear-gradient(
|
||||
135deg,
|
||||
rgba(102, 126, 234, 0.9) 0%,
|
||||
rgba(118, 75, 162, 0.9) 100%
|
||||
);
|
||||
backdrop-filter: blur(10px);
|
||||
|
||||
.hero-title {
|
||||
font-family: var(--font-family-display);
|
||||
background: linear-gradient(45deg, #fff, #e2e8f0);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
}
|
||||
}
|
||||
|
||||
// Feature grid overrides
|
||||
ui-feature-grid, .ui-feature-grid {
|
||||
.feature-item {
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
border-radius: var(--border-radius-lg);
|
||||
padding: 2rem;
|
||||
transition: all 0.3s ease;
|
||||
|
||||
&:hover {
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
transform: scale(1.05);
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Use Component Overrides
|
||||
|
||||
In `src/styles.scss`:
|
||||
|
||||
```scss
|
||||
// Import design system
|
||||
@use 'ui-design-system/src/styles' as ui;
|
||||
|
||||
// Import your component overrides
|
||||
@import 'styles/component-overrides';
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Approach 4: Dark Mode Implementation
|
||||
|
||||
Create a comprehensive dark mode theme.
|
||||
|
||||
### 1. Create Dark Mode Theme
|
||||
|
||||
Create `src/styles/dark-theme.scss`:
|
||||
|
||||
```scss
|
||||
// ==========================================================================
|
||||
// DARK MODE THEME
|
||||
// ==========================================================================
|
||||
@use 'ui-design-system/src/styles' as ui;
|
||||
|
||||
// Dark mode CSS variables
|
||||
[data-theme="dark"] {
|
||||
// ==========================================================================
|
||||
// 🌙 DARK MODE COLORS
|
||||
// ==========================================================================
|
||||
|
||||
// Primary colors (slightly brighter for dark mode)
|
||||
--color-primary: #818cf8; // Lighter indigo
|
||||
--color-secondary: #a78bfa; // Lighter purple
|
||||
--color-tertiary: #34d399; // Lighter emerald
|
||||
|
||||
// Dark surfaces
|
||||
--color-surface: #0f172a; // Very dark blue
|
||||
--color-surface-variant: #1e293b; // Dark blue-gray
|
||||
--color-surface-container: #334155; // Medium blue-gray
|
||||
--color-surface-elevated: #475569; // Light blue-gray
|
||||
--color-surface-dim: #64748b; // Muted blue-gray
|
||||
|
||||
// Dark mode text colors
|
||||
--color-on-surface: #f8fafc; // Light text on dark
|
||||
--color-on-primary: #1e1b4b; // Dark text on light primary
|
||||
--color-on-secondary: #2d1b69; // Dark text on light secondary
|
||||
|
||||
// Border colors for dark mode
|
||||
--color-border: #374151;
|
||||
--color-border-light: #4b5563;
|
||||
|
||||
// ==========================================================================
|
||||
// 🌙 DARK MODE COMPONENT OVERRIDES
|
||||
// ==========================================================================
|
||||
|
||||
// Card styling in dark mode
|
||||
ui-card, .ui-card {
|
||||
background: rgba(30, 41, 59, 0.8);
|
||||
border-color: rgba(71, 85, 105, 0.3);
|
||||
|
||||
&:hover {
|
||||
background: rgba(51, 65, 85, 0.8);
|
||||
border-color: rgba(71, 85, 105, 0.5);
|
||||
}
|
||||
}
|
||||
|
||||
// Input styling in dark mode
|
||||
ui-text-input input, .ui-text-input input {
|
||||
background: rgba(30, 41, 59, 0.8);
|
||||
border-color: var(--color-border);
|
||||
color: var(--color-on-surface);
|
||||
|
||||
&::placeholder {
|
||||
color: #94a3b8;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
background: rgba(30, 41, 59, 1);
|
||||
border-color: var(--color-primary);
|
||||
}
|
||||
}
|
||||
|
||||
// Button adjustments for dark mode
|
||||
ui-button[variant="secondary"], .ui-button--secondary {
|
||||
border-color: var(--color-primary);
|
||||
color: var(--color-primary);
|
||||
|
||||
&:hover {
|
||||
background: var(--color-primary);
|
||||
color: var(--color-on-primary);
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Dark Mode Toggle Component
|
||||
|
||||
Create a theme switcher:
|
||||
|
||||
```typescript
|
||||
// src/app/components/theme-toggle.component.ts
|
||||
import { Component } from '@angular/core';
|
||||
import { ThemeSwitcherComponent } from 'ui-essentials';
|
||||
|
||||
@Component({
|
||||
selector: 'app-theme-toggle',
|
||||
standalone: true,
|
||||
imports: [ThemeSwitcherComponent],
|
||||
template: `
|
||||
<ui-theme-switcher
|
||||
[themes]="themes"
|
||||
(themeChange)="onThemeChange($event)">
|
||||
</ui-theme-switcher>
|
||||
`,
|
||||
styles: [`
|
||||
:host {
|
||||
position: fixed;
|
||||
top: 1rem;
|
||||
right: 1rem;
|
||||
z-index: 1000;
|
||||
}
|
||||
`]
|
||||
})
|
||||
export class ThemeToggleComponent {
|
||||
themes = [
|
||||
{ id: 'light', name: 'Light', icon: '☀️' },
|
||||
{ id: 'dark', name: 'Dark', icon: '🌙' }
|
||||
];
|
||||
|
||||
onThemeChange(theme: string) {
|
||||
document.documentElement.setAttribute('data-theme', theme);
|
||||
localStorage.setItem('theme', theme);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Initialize Theme
|
||||
|
||||
In `src/app/app.component.ts`:
|
||||
|
||||
```typescript
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { ThemeToggleComponent } from './components/theme-toggle.component';
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
standalone: true,
|
||||
imports: [ThemeToggleComponent],
|
||||
template: `
|
||||
<div class="app">
|
||||
<app-theme-toggle></app-theme-toggle>
|
||||
<!-- Your app content -->
|
||||
</div>
|
||||
`
|
||||
})
|
||||
export class AppComponent implements OnInit {
|
||||
ngOnInit() {
|
||||
// Initialize theme from localStorage
|
||||
const savedTheme = localStorage.getItem('theme') || 'light';
|
||||
document.documentElement.setAttribute('data-theme', savedTheme);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Approach 5: Custom Brand Components
|
||||
|
||||
Create your own branded components on top of SSuite.
|
||||
|
||||
### 1. Custom Branded Button
|
||||
|
||||
Create `src/app/components/brand-button.component.ts`:
|
||||
|
||||
```typescript
|
||||
import { Component, Input } from '@angular/core';
|
||||
import { ButtonComponent } from 'ui-essentials';
|
||||
|
||||
@Component({
|
||||
selector: 'app-brand-button',
|
||||
standalone: true,
|
||||
imports: [ButtonComponent],
|
||||
template: `
|
||||
<ui-button
|
||||
[variant]="variant"
|
||||
[size]="size"
|
||||
[disabled]="disabled"
|
||||
class="brand-button"
|
||||
[class.gradient]="gradient"
|
||||
[class.glass]="glass">
|
||||
<ng-content></ng-content>
|
||||
</ui-button>
|
||||
`,
|
||||
styles: [`
|
||||
.brand-button {
|
||||
font-weight: 700;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 1px;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
|
||||
// Gradient effect
|
||||
&.gradient {
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
color: white;
|
||||
border: none;
|
||||
|
||||
&:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: -100%;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: linear-gradient(90deg, transparent, rgba(255,255,255,0.2), transparent);
|
||||
transition: left 0.5s;
|
||||
}
|
||||
|
||||
&:hover:before {
|
||||
left: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
// Glass morphism effect
|
||||
&.glass {
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
backdrop-filter: blur(20px);
|
||||
border: 1px solid rgba(255, 255, 255, 0.2);
|
||||
color: white;
|
||||
|
||||
&:hover {
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
}
|
||||
}
|
||||
}
|
||||
`]
|
||||
})
|
||||
export class BrandButtonComponent {
|
||||
@Input() variant: 'primary' | 'secondary' | 'outline' = 'primary';
|
||||
@Input() size: 'sm' | 'md' | 'lg' = 'md';
|
||||
@Input() disabled = false;
|
||||
@Input() gradient = false;
|
||||
@Input() glass = false;
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Custom Hero Section
|
||||
|
||||
Create `src/app/components/brand-hero.component.ts`:
|
||||
|
||||
```typescript
|
||||
import { Component, Input } from '@angular/core';
|
||||
import { HeroSectionComponent } from 'ui-landing-pages';
|
||||
import { BrandButtonComponent } from './brand-button.component';
|
||||
|
||||
@Component({
|
||||
selector: 'app-brand-hero',
|
||||
standalone: true,
|
||||
imports: [HeroSectionComponent, BrandButtonComponent],
|
||||
template: `
|
||||
<div class="brand-hero">
|
||||
<div class="hero-background"></div>
|
||||
<div class="hero-content">
|
||||
<h1 class="hero-title">{{ title }}</h1>
|
||||
<p class="hero-subtitle">{{ subtitle }}</p>
|
||||
<div class="hero-actions">
|
||||
<app-brand-button
|
||||
[gradient]="true"
|
||||
size="lg">
|
||||
{{ ctaText }}
|
||||
</app-brand-button>
|
||||
<app-brand-button
|
||||
[glass]="true"
|
||||
variant="outline"
|
||||
size="lg">
|
||||
{{ secondaryCta }}
|
||||
</app-brand-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`,
|
||||
styles: [`
|
||||
.brand-hero {
|
||||
position: relative;
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.hero-background {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
|
||||
&:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><circle cx="50" cy="50" r="1" fill="rgba(255,255,255,0.1)"/></svg>') repeat;
|
||||
animation: float 20s infinite linear;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes float {
|
||||
0% { transform: translateY(0) rotate(0deg); }
|
||||
100% { transform: translateY(-100px) rotate(360deg); }
|
||||
}
|
||||
|
||||
.hero-content {
|
||||
text-align: center;
|
||||
z-index: 2;
|
||||
max-width: 800px;
|
||||
padding: 2rem;
|
||||
}
|
||||
|
||||
.hero-title {
|
||||
font-size: clamp(2.5rem, 8vw, 5rem);
|
||||
font-weight: 900;
|
||||
margin-bottom: 1.5rem;
|
||||
background: linear-gradient(45deg, #fff, #e2e8f0);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
line-height: 1.1;
|
||||
}
|
||||
|
||||
.hero-subtitle {
|
||||
font-size: clamp(1.125rem, 3vw, 1.5rem);
|
||||
color: rgba(255, 255, 255, 0.9);
|
||||
margin-bottom: 3rem;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.hero-actions {
|
||||
display: flex;
|
||||
gap: 1.5rem;
|
||||
justify-content: center;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
`]
|
||||
})
|
||||
export class BrandHeroComponent {
|
||||
@Input() title = 'Welcome to Our Platform';
|
||||
@Input() subtitle = 'Create amazing experiences with our design system';
|
||||
@Input() ctaText = 'Get Started';
|
||||
@Input() secondaryCta = 'Learn More';
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Real-World Examples
|
||||
|
||||
### Example 1: E-commerce Theme
|
||||
|
||||
```scss
|
||||
// src/styles/ecommerce-theme.scss
|
||||
:root {
|
||||
// E-commerce focused colors
|
||||
--color-primary: #059669; // Forest green (trust)
|
||||
--color-secondary: #dc2626; // Red (urgency/sales)
|
||||
--color-success: #10b981; // Success green
|
||||
--color-warning: #f59e0b; // Warning amber
|
||||
|
||||
// Product-focused typography
|
||||
--font-family-sans: 'Open Sans', sans-serif;
|
||||
--font-family-display: 'Poppins', sans-serif;
|
||||
|
||||
// E-commerce spacing
|
||||
--spacing-product-card: 1.25rem;
|
||||
--spacing-checkout: 2rem;
|
||||
|
||||
// Trust-building shadows
|
||||
--shadow-product-card: 0 4px 12px rgba(0,0,0,0.1);
|
||||
--shadow-button-primary: 0 4px 14px rgba(5,150,105,0.3);
|
||||
}
|
||||
|
||||
// Product card styling
|
||||
.product-card {
|
||||
border-radius: var(--border-radius-lg);
|
||||
box-shadow: var(--shadow-product-card);
|
||||
transition: all 0.3s ease;
|
||||
|
||||
&:hover {
|
||||
transform: translateY(-4px);
|
||||
box-shadow: 0 12px 24px rgba(0,0,0,0.15);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Example 2: SaaS Platform Theme
|
||||
|
||||
```scss
|
||||
// src/styles/saas-theme.scss
|
||||
:root {
|
||||
// SaaS professional colors
|
||||
--color-primary: #3b82f6; // Professional blue
|
||||
--color-secondary: #6366f1; // Indigo accent
|
||||
--color-success: #10b981; // Success green
|
||||
|
||||
// Dashboard-focused spacing
|
||||
--spacing-sidebar: 16rem;
|
||||
--spacing-dashboard-padding: 2rem;
|
||||
--spacing-card-gap: 1.5rem;
|
||||
|
||||
// Modern typography
|
||||
--font-family-sans: 'Inter', sans-serif;
|
||||
--font-size-dashboard-title: 2rem;
|
||||
--font-size-widget-title: 1.25rem;
|
||||
}
|
||||
|
||||
// Dashboard layout
|
||||
.dashboard-layout {
|
||||
display: grid;
|
||||
grid-template-columns: var(--spacing-sidebar) 1fr;
|
||||
min-height: 100vh;
|
||||
|
||||
.sidebar {
|
||||
background: var(--color-surface-variant);
|
||||
border-right: 1px solid var(--color-border);
|
||||
}
|
||||
|
||||
.main-content {
|
||||
padding: var(--spacing-dashboard-padding);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📚 Advanced Customization Tips
|
||||
|
||||
### 1. Use CSS Custom Properties for Runtime Changes
|
||||
|
||||
```typescript
|
||||
// Dynamically change theme colors
|
||||
export class ThemeService {
|
||||
setThemeColor(property: string, value: string) {
|
||||
document.documentElement.style.setProperty(`--${property}`, value);
|
||||
}
|
||||
|
||||
// Example: User customization
|
||||
applyUserTheme(userTheme: UserTheme) {
|
||||
this.setThemeColor('color-primary', userTheme.primaryColor);
|
||||
this.setThemeColor('font-family-sans', userTheme.fontFamily);
|
||||
this.setThemeColor('border-radius-base', userTheme.borderRadius);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Component-Level CSS Custom Properties
|
||||
|
||||
```scss
|
||||
ui-button {
|
||||
// Component-specific custom properties
|
||||
--btn-padding-x: 2rem;
|
||||
--btn-font-weight: 700;
|
||||
--btn-border-radius: 0.75rem;
|
||||
}
|
||||
|
||||
// Modify specific button instances
|
||||
.hero-button {
|
||||
--btn-padding-x: 3rem;
|
||||
--btn-font-size: 1.25rem;
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Responsive Theme Adjustments
|
||||
|
||||
```scss
|
||||
:root {
|
||||
--font-size-hero: 2.5rem;
|
||||
--spacing-section: 3rem;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
:root {
|
||||
--font-size-hero: 4rem;
|
||||
--spacing-section: 5rem;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ✅ Best Practices
|
||||
|
||||
### 1. **Layer Your Customizations**
|
||||
- Start with CSS custom properties for quick changes
|
||||
- Use SCSS variables for deeper customizations
|
||||
- Create component overrides for specific needs
|
||||
|
||||
### 2. **Maintain Consistency**
|
||||
- Define a clear color palette
|
||||
- Use consistent spacing scales
|
||||
- Maintain typography hierarchy
|
||||
|
||||
### 3. **Test Across Components**
|
||||
- Ensure your theme works across all SSuite components
|
||||
- Test in both light and dark modes
|
||||
- Verify accessibility (contrast ratios)
|
||||
|
||||
### 4. **Performance Considerations**
|
||||
- Use CSS custom properties for dynamic changes
|
||||
- Avoid excessive nesting in component overrides
|
||||
- Minimize redundant style declarations
|
||||
|
||||
### 5. **Documentation**
|
||||
- Document your theme variables
|
||||
- Create a style guide for your team
|
||||
- Maintain examples of themed components
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Quick Start Templates
|
||||
|
||||
### Minimal Customization (5 minutes)
|
||||
```scss
|
||||
// src/styles.scss
|
||||
@use 'ui-design-system/src/styles' as ui;
|
||||
|
||||
:root {
|
||||
--color-primary: #your-brand-color;
|
||||
--font-family-sans: 'Your Font', sans-serif;
|
||||
}
|
||||
```
|
||||
|
||||
### Medium Customization (30 minutes)
|
||||
- Use Approach 1 (CSS Custom Properties)
|
||||
- Add dark mode support
|
||||
- Create 2-3 component overrides
|
||||
|
||||
### Full Customization (2+ hours)
|
||||
- Use Approach 2 (SCSS Variable Overrides)
|
||||
- Implement comprehensive dark mode
|
||||
- Create branded components
|
||||
- Add responsive theme adjustments
|
||||
|
||||
---
|
||||
|
||||
## 🎉 You're Ready to Theme!
|
||||
|
||||
With this guide, you can create beautiful, branded experiences using the SSuite library ecosystem. Start small with CSS custom properties and gradually add more advanced customizations as needed.
|
||||
|
||||
Your themed application will maintain the robust functionality of SSuite components while expressing your unique brand identity! 🎨✨
|
||||
Reference in New Issue
Block a user