react-theme-system
Version:
A comprehensive React theme management system that enforces consistency, supports dark/light mode, and eliminates hardcoded styles
256 lines (231 loc) • 7.39 kB
CSS
/* React Theme System - CSS Variables with Fallbacks */
/* This file provides CSS variables with fallbacks for graceful degradation */
/* System theme detection */
@media (prefers-color-scheme: dark) {
:root {
/* Dark theme defaults when system prefers dark */
--color-primary: #60a5fa;
--color-secondary: #818cf8;
--color-accent: #34d399;
--color-background: #0f172a;
--color-surface: #1e293b;
--color-text-primary: #f8fafc;
--color-text-secondary: #cbd5e1;
--color-text-disabled: #64748b;
--color-border: #334155;
--color-error: #f87171;
--color-warning: #fbbf24;
--color-success: #4ade80;
--color-info: #60a5fa;
}
}
@media (prefers-color-scheme: light) {
:root {
/* Light theme defaults when system prefers light */
--color-primary: #4361ee;
--color-secondary: #3f37c9;
--color-accent: #4895ef;
--color-background: #ffffff;
--color-surface: #f8f9fa;
--color-text-primary: #212529;
--color-text-secondary: #6c757d;
--color-text-disabled: #adb5bd;
--color-border: #dee2e6;
--color-error: #dc3545;
--color-warning: #ffc107;
--color-success: #28a745;
--color-info: #17a2b8;
}
}
/* Base fallbacks (light theme) */
:root {
/* Colors */
--color-primary: #4361ee;
--color-secondary: #3f37c9;
--color-accent: #4895ef;
--color-background: #ffffff;
--color-surface: #f8f9fa;
--color-text-primary: #212529;
--color-text-secondary: #6c757d;
--color-text-disabled: #adb5bd;
--color-border: #dee2e6;
--color-error: #dc3545;
--color-warning: #ffc107;
--color-success: #28a745;
--color-info: #17a2b8;
/* Spacing */
--spacing-xs: 0.25rem;
--spacing-sm: 0.5rem;
--spacing-md: 1rem;
--spacing-lg: 1.5rem;
--spacing-xl: 3rem;
--spacing-xxl: 4rem;
/* Typography */
--font-family-primary: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
--font-family-secondary: Georgia, "Times New Roman", serif;
--font-family-mono: SFMono-Regular, Consolas, "Liberation Mono", Menlo, monospace;
--font-size-xs: 0.75rem;
--font-size-sm: 0.875rem;
--font-size-base: 1rem;
--font-size-lg: 1.125rem;
--font-size-xl: 1.25rem;
--font-size-2xl: 1.5rem;
--font-size-3xl: 1.875rem;
--font-size-4xl: 2.25rem;
--font-weight-light: 300;
--font-weight-normal: 400;
--font-weight-medium: 500;
--font-weight-semibold: 600;
--font-weight-bold: 700;
--line-height-tight: 1.25;
--line-height-normal: 1.5;
--line-height-relaxed: 1.75;
/* Shadows */
--shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
--shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
--shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
--shadow-xl: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
--shadow-2xl: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
--shadow-inner: inset 0 2px 4px 0 rgba(0, 0, 0, 0.06);
--shadow-none: none;
/* Border Radius */
--radius-none: 0;
--radius-sm: 0.125rem;
--radius-md: 0.375rem;
--radius-lg: 0.5rem;
--radius-xl: 0.75rem;
--radius-full: 9999px;
/* Breakpoints */
--breakpoint-sm: 640px;
--breakpoint-md: 768px;
--breakpoint-lg: 1024px;
--breakpoint-xl: 1280px;
--breakpoint-2xl: 1536px;
/* Transitions */
--transition-fast: 150ms ease-in-out;
--transition-normal: 300ms ease-in-out;
--transition-slow: 500ms ease-in-out;
--transition-ease-in: ease-in;
--transition-ease-out: ease-out;
--transition-ease-in-out: ease-in-out;
/* Z-Index */
--z-index-hide: -1;
--z-index-auto: 0;
--z-index-base: 0;
--z-index-docked: 10;
--z-index-dropdown: 1000;
--z-index-sticky: 1100;
--z-index-banner: 1200;
--z-index-overlay: 1300;
--z-index-modal: 1400;
--z-index-popover: 1500;
--z-index-skip-link: 1600;
--z-index-toast: 1700;
--z-index-tooltip: 1800;
}
/* Dark theme overrides */
[data-theme="dark"] {
/* Colors */
--color-primary: #60a5fa;
--color-secondary: #818cf8;
--color-accent: #34d399;
--color-background: #0f172a;
--color-surface: #1e293b;
--color-text-primary: #f8fafc;
--color-text-secondary: #cbd5e1;
--color-text-disabled: #64748b;
--color-border: #334155;
--color-error: #f87171;
--color-warning: #fbbf24;
--color-success: #4ade80;
--color-info: #60a5fa;
/* Shadows - darker for dark theme */
--shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.3);
--shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.4), 0 2px 4px -1px rgba(0, 0, 0, 0.3);
--shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.4), 0 4px 6px -2px rgba(0, 0, 0, 0.3);
--shadow-xl: 0 20px 25px -5px rgba(0, 0, 0, 0.4), 0 10px 10px -5px rgba(0, 0, 0, 0.3);
--shadow-2xl: 0 25px 50px -12px rgba(0, 0, 0, 0.5);
--shadow-inner: inset 0 2px 4px 0 rgba(0, 0, 0, 0.3);
}
/* Light theme explicit override */
[data-theme="light"] {
/* Colors */
--color-primary: #4361ee;
--color-secondary: #3f37c9;
--color-accent: #4895ef;
--color-background: #ffffff;
--color-surface: #f8f9fa;
--color-text-primary: #212529;
--color-text-secondary: #6c757d;
--color-text-disabled: #adb5bd;
--color-border: #dee2e6;
--color-error: #dc3545;
--color-warning: #ffc107;
--color-success: #28a745;
--color-info: #17a2b8;
/* Shadows - lighter for light theme */
--shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
--shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
--shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
--shadow-xl: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
--shadow-2xl: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
--shadow-inner: inset 0 2px 4px 0 rgba(0, 0, 0, 0.06);
}
/* Utility classes for common theme patterns */
.theme-transition {
transition: color var(--transition-normal), background-color var(--transition-normal), border-color var(--transition-normal);
}
.theme-focus {
outline: 2px solid var(--color-primary);
outline-offset: 2px;
}
.theme-focus-visible {
outline: 2px solid var(--color-primary);
outline-offset: 2px;
}
/* High contrast mode support */
@media (prefers-contrast: high) {
:root {
--color-primary: #0000ff;
--color-secondary: #000080;
--color-accent: #008000;
--color-background: #ffffff;
--color-surface: #f0f0f0;
--color-text-primary: #000000;
--color-text-secondary: #333333;
--color-text-disabled: #666666;
--color-border: #000000;
--color-error: #ff0000;
--color-warning: #ff8000;
--color-success: #008000;
--color-info: #0000ff;
}
[data-theme="dark"] {
--color-primary: #ffff00;
--color-secondary: #ffff80;
--color-accent: #80ff80;
--color-background: #000000;
--color-surface: #1a1a1a;
--color-text-primary: #ffffff;
--color-text-secondary: #cccccc;
--color-text-disabled: #999999;
--color-border: #ffffff;
--color-error: #ff8080;
--color-warning: #ffcc80;
--color-success: #80ff80;
--color-info: #8080ff;
}
}
/* Reduced motion support */
@media (prefers-reduced-motion: reduce) {
:root {
--transition-fast: 0ms;
--transition-normal: 0ms;
--transition-slow: 0ms;
}
* {
animation-duration: 0.01ms ;
animation-iteration-count: 1 ;
transition-duration: 0.01ms ;
}
}