# WooNooW Customer SPA Theme System ## ๐ŸŽจ Design Philosophy **SaaS Approach:** Curated options over infinite flexibility - โœ… 4 master layouts (not infinite themes) - Classic, Modern, Boutique (multi-product stores) - Launch (single product funnels) ๐Ÿ†• - โœ… Design tokens (not custom CSS) - โœ… Preset combinations (not freestyle design) - โœ… Accessibility built-in (WCAG 2.1 AA) - โœ… Performance optimized (Core Web Vitals) --- ## ๐Ÿ—๏ธ Theme Architecture ### Design Token System All styling is controlled via CSS custom properties (design tokens): ```css :root { /* Colors */ --color-primary: #3B82F6; --color-secondary: #8B5CF6; --color-accent: #10B981; --color-background: #FFFFFF; --color-text: #1F2937; /* Typography */ --font-heading: 'Inter', sans-serif; --font-body: 'Lora', serif; --font-size-base: 16px; --line-height-base: 1.5; /* Spacing (8px grid) */ --space-1: 0.5rem; /* 8px */ --space-2: 1rem; /* 16px */ --space-3: 1.5rem; /* 24px */ --space-4: 2rem; /* 32px */ --space-6: 3rem; /* 48px */ --space-8: 4rem; /* 64px */ /* Border Radius */ --radius-sm: 0.25rem; /* 4px */ --radius-md: 0.5rem; /* 8px */ --radius-lg: 1rem; /* 16px */ /* Shadows */ --shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05); --shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1); --shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1); /* Transitions */ --transition-fast: 150ms ease; --transition-base: 250ms ease; --transition-slow: 350ms ease; } ``` --- ## ๐Ÿ“ Master Layouts ### 1. Classic Layout **Target Audience:** Traditional ecommerce, B2B **Characteristics:** - Header: Logo left, menu right, search bar - Shop: Sidebar filters (left), product grid (right) - Product: Image gallery left, details right - Footer: 4-column widget areas **File:** `customer-spa/src/layouts/ClassicLayout.tsx` ```typescript export function ClassicLayout({ children }) { return (
{children}
); } ``` **CSS:** ```css .classic-layout { --header-height: 80px; --sidebar-width: 280px; } .classic-main { display: grid; grid-template-columns: var(--sidebar-width) 1fr; gap: var(--space-6); max-width: 1280px; margin: 0 auto; padding: var(--space-6); } @media (max-width: 768px) { .classic-main { grid-template-columns: 1fr; } } ``` ### 2. Modern Layout (Default) **Target Audience:** Fashion, lifestyle, modern brands **Characteristics:** - Header: Centered logo, minimal menu - Shop: Top filters (no sidebar), large product cards - Product: Full-width gallery, sticky details - Footer: Minimal, centered **File:** `customer-spa/src/layouts/ModernLayout.tsx` ```typescript export function ModernLayout({ children }) { return (
{children}
); } ``` **CSS:** ```css .modern-layout { --header-height: 100px; --content-max-width: 1440px; } .modern-main { max-width: var(--content-max-width); margin: 0 auto; padding: var(--space-8) var(--space-4); } .modern-layout .product-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: var(--space-6); } ``` ### 3. Boutique Layout **Target Audience:** Luxury, high-end fashion **Characteristics:** - Header: Full-width, transparent overlay - Shop: Masonry grid, elegant typography - Product: Minimal UI, focus on imagery - Footer: Elegant, serif typography **File:** `customer-spa/src/layouts/BoutiqueLayout.tsx` ```typescript export function BoutiqueLayout({ children }) { return (
{children}
); } ``` **CSS:** ```css .boutique-layout { --header-height: 120px; --content-max-width: 1600px; font-family: var(--font-heading); } .boutique-main { max-width: var(--content-max-width); margin: 0 auto; } .boutique-layout .product-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(400px, 1fr)); gap: var(--space-8); } ``` ### 4. Launch Layout ๐Ÿ†• (Single Product Funnel) **Target Audience:** Single product sellers, course creators, SaaS, product launchers **Important:** Landing page is **fully custom** (user builds with their page builder). WooNooW SPA only takes over **from checkout onwards** after CTA button is clicked. **Characteristics:** - **Landing page:** User's custom design (Elementor, Divi, etc.) - NOT controlled by WooNooW - **Checkout onwards:** WooNooW SPA takes full control - **No traditional header/footer** on SPA pages (distraction-free) - **Streamlined checkout** (one-page, minimal fields, no cart) - **Upsell opportunity** on thank you page - **Direct access** to product in My Account **Page Flow:** ``` Landing Page (Custom - User's Page Builder) โ†“ [CTA Button Click] โ† User directs to /checkout โ†“ Checkout (WooNooW SPA - Full screen, no distractions) โ†“ Thank You (WooNooW SPA - Upsell/downsell opportunity) โ†“ My Account (WooNooW SPA - Access product/download) ``` **Technical Note:** - Landing page URL: Any (/, /landing, /offer, etc.) - CTA button links to: `/checkout` or `/checkout?add-to-cart=123` - WooNooW SPA activates only on checkout, thank you, and account pages - This is essentially **Checkout-Only mode** with optimized funnel design **File:** `customer-spa/src/layouts/LaunchLayout.tsx` ```typescript export function LaunchLayout({ children }) { const location = useLocation(); const isLandingPage = location.pathname === '/' || location.pathname === '/shop'; return (
{/* Minimal header only on non-landing pages */} {!isLandingPage &&
}
{children}
{/* No footer on landing page */} {!isLandingPage &&
); } ``` **CSS:** ```css .launch-layout { --content-max-width: 1200px; min-height: 100vh; } .launch-main { max-width: var(--content-max-width); margin: 0 auto; } /* Landing page: full-screen hero */ .launch-landing { min-height: 100vh; display: flex; flex-direction: column; justify-content: center; align-items: center; text-align: center; padding: var(--space-8); } .launch-landing .hero-title { font-size: var(--text-5xl); font-weight: 700; margin-bottom: var(--space-4); } .launch-landing .hero-subtitle { font-size: var(--text-xl); margin-bottom: var(--space-8); opacity: 0.8; } .launch-landing .cta-button { font-size: var(--text-xl); padding: var(--space-4) var(--space-8); min-width: 300px; } /* Checkout: streamlined, no distractions */ .launch-checkout { max-width: 600px; margin: var(--space-8) auto; padding: var(--space-6); } /* Thank you: upsell opportunity */ .launch-thankyou { max-width: 800px; margin: var(--space-8) auto; text-align: center; } .launch-thankyou .upsell-section { margin-top: var(--space-8); padding: var(--space-6); border: 2px solid var(--color-primary); border-radius: var(--radius-lg); } ``` **Perfect For:** - Digital products (courses, ebooks, software) - SaaS trial โ†’ paid conversions - Webinar funnels - High-ticket consulting - Limited-time offers - Crowdfunding campaigns - Product launches **Competitive Advantage:** Replaces expensive tools like CartFlows ($297-997/year) with built-in, optimized funnel. --- ## ๐ŸŽจ Color System ### Color Palette Generation When user sets primary color, we auto-generate shades: ```typescript function generateColorShades(baseColor: string) { return { 50: lighten(baseColor, 0.95), 100: lighten(baseColor, 0.90), 200: lighten(baseColor, 0.75), 300: lighten(baseColor, 0.60), 400: lighten(baseColor, 0.40), 500: baseColor, // Base color 600: darken(baseColor, 0.10), 700: darken(baseColor, 0.20), 800: darken(baseColor, 0.30), 900: darken(baseColor, 0.40), }; } ``` ### Contrast Checking Ensure WCAG AA compliance: ```typescript function ensureContrast(textColor: string, bgColor: string) { const contrast = getContrastRatio(textColor, bgColor); if (contrast < 4.5) { // Adjust text color for better contrast return adjustColorForContrast(textColor, bgColor, 4.5); } return textColor; } ``` ### Dark Mode Support ```css @media (prefers-color-scheme: dark) { :root { --color-background: #1F2937; --color-text: #F9FAFB; /* Invert shades */ } } ``` --- ## ๐Ÿ“ Typography System ### Typography Presets #### Professional ```css :root { --font-heading: 'Inter', -apple-system, sans-serif; --font-body: 'Lora', Georgia, serif; --font-weight-heading: 700; --font-weight-body: 400; } ``` #### Modern ```css :root { --font-heading: 'Poppins', -apple-system, sans-serif; --font-body: 'Roboto', -apple-system, sans-serif; --font-weight-heading: 600; --font-weight-body: 400; } ``` #### Elegant ```css :root { --font-heading: 'Playfair Display', Georgia, serif; --font-body: 'Source Sans Pro', -apple-system, sans-serif; --font-weight-heading: 700; --font-weight-body: 400; } ``` #### Tech ```css :root { --font-heading: 'Space Grotesk', monospace; --font-body: 'IBM Plex Mono', monospace; --font-weight-heading: 700; --font-weight-body: 400; } ``` ### Type Scale ```css :root { --text-xs: 0.75rem; /* 12px */ --text-sm: 0.875rem; /* 14px */ --text-base: 1rem; /* 16px */ --text-lg: 1.125rem; /* 18px */ --text-xl: 1.25rem; /* 20px */ --text-2xl: 1.5rem; /* 24px */ --text-3xl: 1.875rem; /* 30px */ --text-4xl: 2.25rem; /* 36px */ --text-5xl: 3rem; /* 48px */ } ``` --- ## ๐Ÿงฉ Component Theming ### Button Component ```typescript // components/ui/button.tsx export function Button({ variant = 'primary', ...props }) { return ( ); } ``` ```css .product-card { background: var(--color-background); border-radius: var(--radius-lg); overflow: hidden; transition: all var(--transition-base); } .product-card:hover { box-shadow: var(--shadow-lg); transform: translateY(-4px); } .product-card-modern { /* Modern layout specific styles */ padding: var(--space-4); } .product-card-boutique { /* Boutique layout specific styles */ padding: 0; } ``` --- ## ๐ŸŽญ Theme Provider (React Context) ### Implementation **File:** `customer-spa/src/contexts/ThemeContext.tsx` ```typescript import { createContext, useContext, useEffect, ReactNode } from 'react'; interface ThemeConfig { layout: 'classic' | 'modern' | 'boutique'; colors: { primary: string; secondary: string; accent: string; background: string; text: string; }; typography: { preset: string; customFonts?: { heading: string; body: string; }; }; } const ThemeContext = createContext(null); export function ThemeProvider({ config, children }: { config: ThemeConfig; children: ReactNode; }) { useEffect(() => { // Inject CSS variables const root = document.documentElement; // Colors root.style.setProperty('--color-primary', config.colors.primary); root.style.setProperty('--color-secondary', config.colors.secondary); root.style.setProperty('--color-accent', config.colors.accent); root.style.setProperty('--color-background', config.colors.background); root.style.setProperty('--color-text', config.colors.text); // Typography loadTypographyPreset(config.typography.preset); // Add layout class to body document.body.className = `layout-${config.layout}`; }, [config]); return ( {children} ); } export function useTheme() { const context = useContext(ThemeContext); if (!context) { throw new Error('useTheme must be used within ThemeProvider'); } return context; } ``` ### Loading Google Fonts ```typescript function loadTypographyPreset(preset: string) { const fontMap = { professional: ['Inter:400,600,700', 'Lora:400,700'], modern: ['Poppins:400,600,700', 'Roboto:400,700'], elegant: ['Playfair+Display:400,700', 'Source+Sans+Pro:400,700'], tech: ['Space+Grotesk:400,700', 'IBM+Plex+Mono:400,700'], }; const fonts = fontMap[preset]; if (!fonts) return; const link = document.createElement('link'); link.href = `https://fonts.googleapis.com/css2?family=${fonts.join('&family=')}&display=swap`; link.rel = 'stylesheet'; document.head.appendChild(link); } ``` --- ## ๐Ÿ“ฑ Responsive Design ### Breakpoints ```css :root { --breakpoint-sm: 640px; --breakpoint-md: 768px; --breakpoint-lg: 1024px; --breakpoint-xl: 1280px; --breakpoint-2xl: 1536px; } ``` ### Mobile-First Approach ```css /* Mobile (default) */ .product-grid { grid-template-columns: 1fr; gap: var(--space-4); } /* Tablet */ @media (min-width: 768px) { .product-grid { grid-template-columns: repeat(2, 1fr); gap: var(--space-6); } } /* Desktop */ @media (min-width: 1024px) { .product-grid { grid-template-columns: repeat(3, 1fr); } } /* Large Desktop */ @media (min-width: 1280px) { .product-grid { grid-template-columns: repeat(4, 1fr); } } ``` --- ## โ™ฟ Accessibility ### Focus States ```css :focus-visible { outline: 2px solid var(--color-primary); outline-offset: 2px; } button:focus-visible { box-shadow: 0 0 0 3px var(--color-primary-200); } ``` ### Screen Reader Support ```typescript ``` ### Color Contrast All text must meet WCAG AA standards (4.5:1 for normal text, 3:1 for large text). --- ## ๐Ÿš€ Performance Optimization ### CSS-in-JS vs CSS Variables We use **CSS variables** instead of CSS-in-JS for better performance: - โœ… No runtime overhead - โœ… Instant theme switching - โœ… Better browser caching - โœ… Smaller bundle size ### Critical CSS Inline critical CSS in ``: ```php ``` ### Font Loading Strategy ```html ``` --- ## ๐Ÿงช Testing ### Visual Regression Testing ```typescript describe('Theme System', () => { it('should apply modern layout correctly', () => { cy.visit('/shop?theme=modern'); cy.matchImageSnapshot('shop-modern-layout'); }); it('should apply custom colors', () => { cy.setTheme({ colors: { primary: '#FF0000' } }); cy.get('.btn-primary').should('have.css', 'background-color', 'rgb(255, 0, 0)'); }); }); ``` ### Accessibility Testing ```typescript it('should meet WCAG AA standards', () => { cy.visit('/shop'); cy.injectAxe(); cy.checkA11y(); }); ``` --- ## ๐Ÿ“š Related Documentation - [Customer SPA Architecture](./CUSTOMER_SPA_ARCHITECTURE.md) - [Customer SPA Settings](./CUSTOMER_SPA_SETTINGS.md) - [Component Library](./COMPONENT_LIBRARY.md)