Files
MyClub/DOCS/MYUIBRIX_CSS_ARCHITECTURE.md
Tomáš Dvořák 12cba639b9 upload
2025-10-16 13:32:05 +02:00

13 KiB

🎨 MyUIbrix CSS Architecture Guide

📋 Overview

Your project uses a hybrid CSS approach combining Chakra UI (CSS-in-JS) with traditional CSS files. Here's how CSS works with MyUIbrix and your elements.


🏗️ Current CSS Architecture

1. Chakra UI (Primary Styling System)

// From package.json
"@chakra-ui/react": "^2.8.2"
"@emotion/react": "^11.11.1"       // Chakra's CSS-in-JS engine
"@emotion/styled": "^11.11.0"

How it works:

  • Chakra UI uses @emotion for CSS-in-JS
  • Styles are written as props directly on components
  • No separate CSS files needed for Chakra components

Example from your code:

<Box bg="white" p={4} borderRadius="xl" boxShadow="sm">
  <Heading size="lg" mb={4} color="blue.500">
    Title
  </Heading>
</Box>

2. Global CSS Files (Imported at App Level)

// From index.tsx
import './index.css';
import './styles/global-enhancements.css';
import './styles/admin-enhancements.css';

Your current CSS files:

frontend/src/styles/
├── admin-enhancements.css      # Admin-specific styles
├── custom-editor.css           # Rich editor styles
├── designSystem.css            # Design system
├── designSystem.module.css     # Modular design system
├── global-enhancements.css     # Global utilities
├── globals.css                 # Base globals
├── logos.css                   # Logo styling
├── sparta-styles.css           # ⚽ NEW: Sparta elements
└── theme.css                   # Theme variables

When loaded: Once at app startup
Scope: Global - available everywhere
Use case: Global utilities, resets, theme variables


3. Page-Specific CSS Files

// From HomePage.tsx
import '../styles/theme.css';
import './styles/UnifiedHome.css';

When loaded: When the specific page/component mounts
Scope: Global (but only loaded when needed)
Use case: Page-specific complex layouts


4. Component-Scoped CSS Classes

// Using className with global CSS
<Box className="sparta-slider-container sparta-container">
  <Heading className="sparta-slider-title">Videos</Heading>
</Box>

When loaded: CSS file must be imported somewhere in the component tree
Scope: Global classes, but named to avoid conflicts
Use case: Complex component styling with custom animations


How Sparta CSS Works with MyUIbrix

Current Approach (What I Created)

// In App.tsx or index.tsx
import './styles/sparta-styles.css';

Pros:

  • Simple - one import, works everywhere
  • All Sparta elements have access to styles
  • No duplicate CSS
  • Easy to maintain

Cons:

  • ⚠️ CSS bundle is always loaded (even if Sparta elements not used)
  • ⚠️ Global namespace (but we use BEM-style naming to avoid conflicts)

Option 2: Component-Level Import (Alternative)

// In each Sparta component
import '../../styles/sparta-styles.css';

Pros:

  • CSS only loaded when component is used
  • Co-located with component

Cons:

  • ⚠️ If multiple Sparta components used, CSS imported multiple times
  • ⚠️ Webpack/React handles deduplication, but more imports to manage

Option 3: Split into Modular Files (Best for Production)

frontend/src/styles/sparta/
├── sparta-navbar.css
├── sparta-hero.css
├── sparta-slider.css
├── sparta-tabs.css
├── sparta-products.css
├── sparta-footer.css
└── sparta-utilities.css
// In each component
import '../../styles/sparta/sparta-slider.css';

Pros:

  • Only load CSS for components actually used
  • Smaller bundle per component
  • Better code splitting

Cons:

  • ⚠️ More files to manage
  • ⚠️ Need to track dependencies (utilities used by multiple)

🔧 MyUIbrix Element Styling Patterns

Pattern A: Pure Chakra UI (Current MyUIbrix Style)

// No CSS files needed
const MyElement = () => (
  <Box bg="gray.800" p={4} borderRadius="md">
    <Heading size="lg" color="white">Title</Heading>
    <Text color="gray.400">Description</Text>
  </Box>
);

Used for:

  • Simple layouts
  • Admin interfaces
  • Form elements
  • Most existing MyUIbrix UI

Pattern B: Chakra + Custom Classes (Sparta Elements)

// Import CSS file
import '../../styles/sparta-styles.css';

const SpartaElement = () => (
  <Box className="sparta-slider-container sparta-section">
    <Heading className="sparta-slider-title" as="h2">
      Videos
    </Heading>
    <Flex className="sparta-slider-track" gap={4}>
      {/* slides */}
    </Flex>
  </Box>
);

Used for:

  • Complex animations
  • Specific design systems (Sparta)
  • Custom hover effects
  • Pseudo-elements (::before, ::after)

Why? Some CSS features aren't easily done in Chakra:

  • CSS animations with keyframes
  • Complex pseudo-elements
  • Gradient overlays with position
  • Transform-based animations

Pattern C: CSS Modules (Not currently used, but available)

// sparta-slider.module.css
import styles from './sparta-slider.module.css';

const SpartaSlider = () => (
  <div className={styles.container}>
    <h2 className={styles.title}>Videos</h2>
  </div>
);

Pros:

  • Scoped CSS (no global namespace pollution)
  • Auto-generated unique class names

Cons:

  • ⚠️ Not used in your current setup
  • ⚠️ Would require refactoring

For Development/Testing (Current)

// In App.tsx or index.tsx (ONE TIME)
import './styles/sparta-styles.css';

Then use classes in components:

<Box className="sparta-slider-container">
  <Heading className="sparta-slider-title">Videos</Heading>
</Box>

For Production (Optimized)

Step 1: Split CSS file

# Create modular files
frontend/src/styles/sparta/
├── _base.css           # Variables, resets
├── navbar.css          # Just navbar styles
├── hero.css            # Just hero styles
├── slider.css          # Just slider styles
├── tabs.css            # Just tabs styles
├── products.css        # Just product styles
├── footer.css          # Just footer styles
└── utilities.css       # Shared utilities

Step 2: Import in components

// SpartaHorizontalSlider.tsx
import '../../styles/sparta/_base.css';        // Variables
import '../../styles/sparta/slider.css';       // Component styles
import '../../styles/sparta/utilities.css';    // Shared utilities

const SpartaHorizontalSlider = () => (
  <Box className="sparta-slider-container">
    {/* ... */}
  </Box>
);

Step 3: Dynamic loading via MyUIbrix settings

// In HomePage or element renderer
const loadSpartaStyles = (variant: string) => {
  if (variant === 'sparta_horizontal_slider') {
    import('../../styles/sparta/slider.css');
  }
  if (variant === 'sparta_navbar') {
    import('../../styles/sparta/navbar.css');
  }
  // ... etc
};

🚀 Integration with MyUIbrix Editor

How Page Elements Use Styles

// From pageElements.ts
export interface PageElementConfig {
  id?: number;
  page_type: string;
  element_name: string;
  variant: string;           // ← This determines which CSS to load
  visible?: boolean;
  display_order?: number;
  settings?: Record<string, any>;
}

Example Element Renderer

// Pseudo-code for rendering elements
const renderElement = (config: PageElementConfig) => {
  const { element_name, variant, settings } = config;
  
  // Determine component and styles based on variant
  switch (variant) {
    case 'sparta_horizontal_slider':
      return <SpartaHorizontalSlider {...settings} />;
      // CSS already imported in component or globally
    
    case 'sparta_navbar':
      return <SpartaNavbar {...settings} />;
    
    default:
      return <DefaultElement {...settings} />;
  }
};

📦 CSS Loading Strategies

Strategy 1: Global Load (Simplest)

// index.tsx or App.tsx
import './styles/sparta-styles.css';

Bundle size: ~16KB (sparta-styles.css)
When: Always loaded
Best for: Small projects, development


Strategy 2: Route-Based (Code Splitting)

// HomePage.tsx
import './styles/sparta-styles.css';

// BlogPage.tsx - doesn't import it

Bundle size: Only loaded on pages that need it
When: When route is accessed
Best for: Medium projects


Strategy 3: Component-Based (Granular)

// SpartaHorizontalSlider.tsx
import '../../styles/sparta/slider.css';

// SpartaNavbar.tsx
import '../../styles/sparta/navbar.css';

Bundle size: Only load what's used
When: When component mounts
Best for: Large projects, optimal performance


Strategy 4: Dynamic Import (Advanced)

// Element renderer
const loadElementStyles = async (variant: string) => {
  switch (variant) {
    case 'sparta_horizontal_slider':
      await import('../../styles/sparta/slider.css');
      break;
    case 'sparta_navbar':
      await import('../../styles/sparta/navbar.css');
      break;
  }
};

// Before rendering
await loadElementStyles(config.variant);

Bundle size: Smallest possible
When: On-demand
Best for: Maximum optimization


🎨 CSS Variables in Sparta Styles

Using CSS Custom Properties

/* sparta-styles.css */
.sparta-slider-container {
  background: var(--colorBgPrimary, #0e0e0e);
  color: var(--colorTextPrimary, #ffffff);
}

Setting Variables from MyUIbrix

// In settings or theme
const spartaTheme = {
  colorBgPrimary: '#0e0e0e',
  colorAccent: '#f03232',
  colorTextPrimary: '#ffffff',
};

// Apply to element
<Box
  className="sparta-slider-container"
  style={{
    '--colorAccent': spartaTheme.colorAccent,
  } as React.CSSProperties}
>

🔄 Migration Path

Current State

✅ Chakra UI everywhere
✅ Global CSS files for complex styles
✅ sparta-styles.css created but not imported

Step 1: Add Sparta CSS (Now)

// App.tsx
import './styles/sparta-styles.css';

Step 2: Test Sparta Elements

// Use in components
<Box className="sparta-slider-container">
  {/* Uses global CSS */}
</Box>

Step 3: Optimize (Later)

  • Split into modular files
  • Implement dynamic imports
  • Add CSS purging in production

📊 Comparison Table

Approach Bundle Size Ease of Use Performance Maintenance
Chakra Only Small
Global CSS Medium
Component CSS Small
CSS Modules Small
Dynamic Import Smallest

Recommendation

For Now (Development)

// 1. Import globally in App.tsx
import './styles/sparta-styles.css';

// 2. Use classes in components
<Box className="sparta-slider-container">
  <Heading className="sparta-slider-title">Videos</Heading>
</Box>

For Later (Production)

  1. Split sparta-styles.css into modular files
  2. Import per-component
  3. Add dynamic loading based on variant
  4. Implement CSS purging (remove unused styles)

🎯 Quick Start

// frontend/src/App.tsx
import './styles/sparta-styles.css';  // Add this line

Option 2: Add to index.tsx

// frontend/src/index.tsx
import './styles/sparta-styles.css';  // Add this line

Option 3: Import in Component

// SpartaHorizontalSlider.tsx - already has this
import '../../styles/sparta-styles.css';

📝 Summary

How CSS works with MyUIbrix:

  1. Primary: Chakra UI (CSS-in-JS via @emotion)
  2. Secondary: Global CSS files for complex styles
  3. Sparta Elements: Custom CSS classes + Chakra UI hybrid

Best practice:

  • Use Chakra UI props for simple styling
  • Use custom CSS classes for complex animations/layouts
  • Import CSS globally for development, per-component for production

Current setup:

  • Sparta CSS file created (sparta-styles.css)
  • Need to import it (one line in App.tsx or index.tsx)
  • Classes already used in SpartaHorizontalSlider.tsx

Next step: Add one import statement and you're ready to use all Sparta elements! 🚀


Created: October 15, 2025
Version: 1.0.0
Status: Ready to implement