fix: add data attributes and Google Fonts to enable theme visual changes
- Add Google Fonts link to root layout for typography presets - Add data-mood, data-typography, data-shape, data-density attributes to preview-frame - Create theme-layer2-attributes.css with attribute-based CSS from demo - Move theme CSS files from priv/static/css to assets/css for proper compilation - Update CSS import order (primitives → layer2 → semantic) - Add 'css' to static_paths to serve theme CSS files This fixes the issue where theme controls updated the database but didn't visually affect the preview. The demo's attribute-based CSS system is now properly integrated with the Phoenix LiveView implementation. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -103,9 +103,12 @@
|
||||
[data-phx-session], [data-phx-teleported-src] { display: contents }
|
||||
|
||||
/* Theme CSS - Layer 1: Primitives (fixed CSS variables) */
|
||||
@import url("/css/theme-primitives.css");
|
||||
@import "./theme-primitives.css";
|
||||
|
||||
/* Theme CSS - Layer 2: Attribute-based theme tokens */
|
||||
@import "./theme-layer2-attributes.css";
|
||||
|
||||
/* Theme CSS - Layer 3: Semantic aliases */
|
||||
@import url("/css/theme-semantic.css");
|
||||
@import "./theme-semantic.css";
|
||||
|
||||
/* This file is for your main application CSS */
|
||||
|
||||
157
assets/css/theme-layer2-attributes.css
Normal file
157
assets/css/theme-layer2-attributes.css
Normal file
@@ -0,0 +1,157 @@
|
||||
/* ========================================
|
||||
LAYER 2: THEME TOKENS (Attribute-based)
|
||||
======================================== */
|
||||
|
||||
/* Mood - Default (Neutral) */
|
||||
.preview-frame {
|
||||
--t-surface-base: #ffffff;
|
||||
--t-surface-raised: #ffffff;
|
||||
--t-surface-sunken: #f5f5f5;
|
||||
--t-surface-overlay: rgba(255, 255, 255, 0.95);
|
||||
--t-text-primary: #171717;
|
||||
--t-text-secondary: #525252;
|
||||
--t-text-tertiary: #a3a3a3;
|
||||
--t-text-inverse: #ffffff;
|
||||
--t-border-default: #e5e5e5;
|
||||
--t-border-subtle: #f0f0f0;
|
||||
}
|
||||
|
||||
.preview-frame[data-mood="warm"] {
|
||||
--t-surface-base: #fdf8f3;
|
||||
--t-surface-raised: #fffcf8;
|
||||
--t-surface-sunken: #f5ebe0;
|
||||
--t-text-primary: #1c1917;
|
||||
--t-text-secondary: #57534e;
|
||||
--t-text-tertiary: #a8a29e;
|
||||
--t-border-default: #e7e0d8;
|
||||
--t-border-subtle: #f0ebe4;
|
||||
}
|
||||
|
||||
.preview-frame[data-mood="cool"] {
|
||||
--t-surface-base: #f4f7fb;
|
||||
--t-surface-raised: #f8fafc;
|
||||
--t-surface-sunken: #e8eff7;
|
||||
--t-text-primary: #0f172a;
|
||||
--t-text-secondary: #475569;
|
||||
--t-text-tertiary: #94a3b8;
|
||||
--t-border-default: #d4dce8;
|
||||
--t-border-subtle: #e8eff5;
|
||||
}
|
||||
|
||||
.preview-frame[data-mood="dark"] {
|
||||
--t-surface-base: #0a0a0a;
|
||||
--t-surface-raised: #171717;
|
||||
--t-surface-sunken: #000000;
|
||||
--t-surface-overlay: rgba(23, 23, 23, 0.95);
|
||||
--t-text-primary: #fafafa;
|
||||
--t-text-secondary: #a3a3a3;
|
||||
--t-text-tertiary: #737373;
|
||||
--t-text-inverse: #171717;
|
||||
--t-border-default: #262626;
|
||||
--t-border-subtle: #1c1c1c;
|
||||
--p-shadow-strength: 0.25;
|
||||
}
|
||||
|
||||
/* Typography - Default (Clean/Inter) */
|
||||
.preview-frame {
|
||||
--t-font-heading: var(--p-font-inter);
|
||||
--t-font-body: var(--p-font-inter);
|
||||
--t-heading-weight: 600;
|
||||
--t-heading-tracking: -0.025em;
|
||||
}
|
||||
|
||||
.preview-frame[data-typography="editorial"] {
|
||||
--t-font-heading: var(--p-font-fraunces);
|
||||
--t-font-body: var(--p-font-source);
|
||||
--t-heading-weight: 600;
|
||||
--t-heading-tracking: -0.02em;
|
||||
}
|
||||
|
||||
.preview-frame[data-typography="modern"] {
|
||||
--t-font-heading: var(--p-font-space);
|
||||
--t-font-body: var(--p-font-space);
|
||||
--t-heading-weight: 500;
|
||||
--t-heading-tracking: -0.03em;
|
||||
}
|
||||
|
||||
.preview-frame[data-typography="classic"] {
|
||||
--t-font-heading: var(--p-font-baskerville);
|
||||
--t-font-body: var(--p-font-source);
|
||||
--t-heading-weight: 400;
|
||||
--t-heading-tracking: 0;
|
||||
}
|
||||
|
||||
.preview-frame[data-typography="friendly"] {
|
||||
--t-font-heading: var(--p-font-nunito);
|
||||
--t-font-body: var(--p-font-nunito);
|
||||
--t-heading-weight: 700;
|
||||
--t-heading-tracking: -0.01em;
|
||||
}
|
||||
|
||||
.preview-frame[data-typography="minimal"] {
|
||||
--t-font-heading: var(--p-font-outfit);
|
||||
--t-font-body: var(--p-font-outfit);
|
||||
--t-heading-weight: 300;
|
||||
--t-heading-tracking: 0;
|
||||
}
|
||||
|
||||
.preview-frame[data-typography="impulse"] {
|
||||
--t-font-heading: var(--p-font-avenir);
|
||||
--t-font-body: var(--p-font-avenir);
|
||||
--t-heading-weight: 300;
|
||||
--t-heading-tracking: 0.02em;
|
||||
}
|
||||
|
||||
/* Shape - Default (Soft) */
|
||||
.preview-frame {
|
||||
--t-radius-sm: var(--p-radius-sm);
|
||||
--t-radius-md: var(--p-radius-md);
|
||||
--t-radius-lg: var(--p-radius-lg);
|
||||
--t-radius-button: var(--p-radius-md);
|
||||
--t-radius-card: var(--p-radius-lg);
|
||||
--t-radius-input: var(--p-radius-md);
|
||||
--t-radius-image: var(--p-radius-md);
|
||||
}
|
||||
|
||||
.preview-frame[data-shape="sharp"] {
|
||||
--t-radius-sm: 0;
|
||||
--t-radius-md: 0;
|
||||
--t-radius-lg: 0;
|
||||
--t-radius-button: 0;
|
||||
--t-radius-card: 0;
|
||||
--t-radius-input: 0;
|
||||
--t-radius-image: 0;
|
||||
}
|
||||
|
||||
.preview-frame[data-shape="round"] {
|
||||
--t-radius-sm: var(--p-radius-md);
|
||||
--t-radius-md: var(--p-radius-lg);
|
||||
--t-radius-lg: var(--p-radius-xl);
|
||||
--t-radius-button: var(--p-radius-lg);
|
||||
--t-radius-card: var(--p-radius-xl);
|
||||
--t-radius-input: var(--p-radius-lg);
|
||||
--t-radius-image: var(--p-radius-lg);
|
||||
}
|
||||
|
||||
.preview-frame[data-shape="pill"] {
|
||||
--t-radius-sm: var(--p-radius-full);
|
||||
--t-radius-md: var(--p-radius-full);
|
||||
--t-radius-lg: var(--p-radius-xl);
|
||||
--t-radius-button: var(--p-radius-full);
|
||||
--t-radius-card: var(--p-radius-xl);
|
||||
--t-radius-input: var(--p-radius-full);
|
||||
--t-radius-image: var(--p-radius-lg);
|
||||
}
|
||||
|
||||
/* Density - Default (Balanced) */
|
||||
.preview-frame {
|
||||
--t-density: 1;
|
||||
}
|
||||
|
||||
.preview-frame[data-density="spacious"] {
|
||||
--t-density: 1.25;
|
||||
}
|
||||
|
||||
.preview-frame[data-density="compact"] {
|
||||
--t-density: 0.85;
|
||||
}
|
||||
58
assets/css/theme-primitives.css
Normal file
58
assets/css/theme-primitives.css
Normal file
@@ -0,0 +1,58 @@
|
||||
/* ========================================
|
||||
THEME PRIMITIVES - Layer 1
|
||||
Fixed CSS custom properties
|
||||
======================================== */
|
||||
|
||||
:root {
|
||||
/* Spacing scale */
|
||||
--p-space-1: 0.25rem;
|
||||
--p-space-2: 0.5rem;
|
||||
--p-space-3: 0.75rem;
|
||||
--p-space-4: 1rem;
|
||||
--p-space-6: 1.5rem;
|
||||
--p-space-8: 2rem;
|
||||
--p-space-12: 3rem;
|
||||
--p-space-16: 4rem;
|
||||
--p-space-24: 6rem;
|
||||
|
||||
/* Border radius scale */
|
||||
--p-radius-none: 0;
|
||||
--p-radius-sm: 0.25rem;
|
||||
--p-radius-md: 0.5rem;
|
||||
--p-radius-lg: 0.75rem;
|
||||
--p-radius-xl: 1rem;
|
||||
--p-radius-full: 9999px;
|
||||
|
||||
/* Font families */
|
||||
--p-font-inter: 'Inter', system-ui, sans-serif;
|
||||
--p-font-fraunces: 'Fraunces', serif;
|
||||
--p-font-source: 'Source Sans 3', system-ui, sans-serif;
|
||||
--p-font-space: 'Space Grotesk', system-ui, sans-serif;
|
||||
--p-font-baskerville: 'Libre Baskerville', Georgia, serif;
|
||||
--p-font-nunito: 'Nunito', system-ui, sans-serif;
|
||||
--p-font-outfit: 'Outfit', system-ui, sans-serif;
|
||||
--p-font-avenir: 'Nunito Sans', 'Avenir Next', 'Avenir', system-ui, sans-serif;
|
||||
|
||||
/* Font size scale */
|
||||
--p-text-xs: 0.75rem;
|
||||
--p-text-sm: 0.875rem;
|
||||
--p-text-base: 1rem;
|
||||
--p-text-lg: 1.125rem;
|
||||
--p-text-xl: 1.25rem;
|
||||
--p-text-2xl: 1.5rem;
|
||||
--p-text-3xl: 1.875rem;
|
||||
--p-text-4xl: 2.25rem;
|
||||
|
||||
/* Animation durations */
|
||||
--p-duration-fast: 0.1s;
|
||||
--p-duration-normal: 0.2s;
|
||||
--p-duration-slow: 0.35s;
|
||||
|
||||
/* Easing functions */
|
||||
--p-ease-out: cubic-bezier(0.25, 0.46, 0.45, 0.94);
|
||||
--p-ease-out-back: cubic-bezier(0.34, 1.56, 0.64, 1);
|
||||
|
||||
/* Shadow base */
|
||||
--p-shadow-color: 0 0% 0%;
|
||||
--p-shadow-strength: 0.06;
|
||||
}
|
||||
80
assets/css/theme-semantic.css
Normal file
80
assets/css/theme-semantic.css
Normal file
@@ -0,0 +1,80 @@
|
||||
/* ========================================
|
||||
THEME SEMANTIC - Layer 3
|
||||
Semantic aliases for easy usage
|
||||
======================================== */
|
||||
|
||||
:root {
|
||||
/* Accent color (dynamic, set by theme) */
|
||||
--t-accent-h: 24;
|
||||
--t-accent-s: 95%;
|
||||
--t-accent-l: 53%;
|
||||
--t-accent: hsl(var(--t-accent-h) var(--t-accent-s) var(--t-accent-l));
|
||||
--t-accent-hover: hsl(var(--t-accent-h) var(--t-accent-s) calc(var(--t-accent-l) - 8%));
|
||||
--t-accent-subtle: hsl(var(--t-accent-h) 40% 95%);
|
||||
--t-accent-ring: hsl(var(--t-accent-h) var(--t-accent-s) var(--t-accent-l) / 0.4);
|
||||
|
||||
/* Secondary colors */
|
||||
--t-secondary-accent: #ea580c;
|
||||
--t-sale-color: #dc2626;
|
||||
|
||||
/* Density multiplier */
|
||||
--t-density: 1;
|
||||
|
||||
/* Layout */
|
||||
--t-layout-max-width: 1400px;
|
||||
--t-button-style: filled;
|
||||
--t-card-shadow: none;
|
||||
--t-product-text-align: left;
|
||||
|
||||
/* Page colors */
|
||||
--color-page: var(--t-surface-base);
|
||||
--color-card: var(--t-surface-raised);
|
||||
--color-input: var(--t-surface-raised);
|
||||
|
||||
/* Text colors */
|
||||
--color-heading: var(--t-text-primary);
|
||||
--color-body: var(--t-text-secondary);
|
||||
--color-caption: var(--t-text-tertiary);
|
||||
|
||||
/* Button colors */
|
||||
--color-button-primary: var(--t-accent);
|
||||
--color-button-primary-hover: var(--t-secondary-accent);
|
||||
--color-button-primary-text: var(--t-text-inverse);
|
||||
|
||||
/* Border colors */
|
||||
--color-border: var(--t-border-default);
|
||||
|
||||
/* Typography */
|
||||
--font-heading: var(--t-font-heading);
|
||||
--font-body: var(--t-font-body);
|
||||
--weight-heading: var(--t-heading-weight);
|
||||
--tracking-heading: var(--t-heading-tracking);
|
||||
|
||||
/* Responsive spacing (density-aware) */
|
||||
--space-xs: calc(var(--p-space-2) * var(--t-density));
|
||||
--space-sm: calc(var(--p-space-3) * var(--t-density));
|
||||
--space-md: calc(var(--p-space-4) * var(--t-density));
|
||||
--space-lg: calc(var(--p-space-6) * var(--t-density));
|
||||
--space-xl: calc(var(--p-space-8) * var(--t-density));
|
||||
--space-2xl: calc(var(--p-space-12) * var(--t-density));
|
||||
|
||||
/* Border radius */
|
||||
--radius-button: var(--t-radius-button);
|
||||
--radius-card: var(--t-radius-card);
|
||||
--radius-input: var(--t-radius-input);
|
||||
--radius-image: var(--t-radius-image);
|
||||
|
||||
/* Shadows */
|
||||
--shadow-sm:
|
||||
0 1px 2px hsl(var(--p-shadow-color) / calc(var(--p-shadow-strength) * 0.5)),
|
||||
0 1px 3px hsl(var(--p-shadow-color) / var(--p-shadow-strength));
|
||||
--shadow-md:
|
||||
0 2px 4px hsl(var(--p-shadow-color) / calc(--p-shadow-strength) * 0.5)),
|
||||
0 4px 8px hsl(var(--p-shadow-color) / var(--p-shadow-strength)),
|
||||
0 8px 16px hsl(var(--p-shadow-color) / calc(var(--p-shadow-strength) * 0.5));
|
||||
|
||||
/* Transitions */
|
||||
--transition-fast: var(--p-duration-fast) var(--p-ease-out);
|
||||
--transition-normal: var(--p-duration-normal) var(--p-ease-out);
|
||||
--transition-bounce: var(--p-duration-normal) var(--p-ease-out-back);
|
||||
}
|
||||
Reference in New Issue
Block a user