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

543 lines
13 KiB
Markdown

# 🎨 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)**
```typescript
// 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:**
```tsx
<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)**
```typescript
// 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**
```typescript
// 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**
```tsx
// 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)
#### **Option 1: Global Import (Recommended for now)**
```typescript
// 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)**
```tsx
// 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
```
```tsx
// 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)
```tsx
// 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)
```tsx
// 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)
```tsx
// 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
---
## 🎯 Recommended Approach for Sparta Elements
### **For Development/Testing (Current)**
```typescript
// In App.tsx or index.tsx (ONE TIME)
import './styles/sparta-styles.css';
```
Then use classes in components:
```tsx
<Box className="sparta-slider-container">
<Heading className="sparta-slider-title">Videos</Heading>
</Box>
```
---
### **For Production (Optimized)**
#### Step 1: Split CSS file
```bash
# 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
```tsx
// 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
```tsx
// 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
```typescript
// 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
```tsx
// 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)
```typescript
// 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)
```typescript
// 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)
```typescript
// 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)
```typescript
// 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
```css
/* sparta-styles.css */
.sparta-slider-container {
background: var(--colorBgPrimary, #0e0e0e);
color: var(--colorTextPrimary, #ffffff);
}
```
### Setting Variables from MyUIbrix
```tsx
// 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)
```typescript
// App.tsx
import './styles/sparta-styles.css';
```
### Step 2: Test Sparta Elements
```tsx
// 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)**
```typescript
// 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
### Option 1: Add to App.tsx (Recommended)
```typescript
// frontend/src/App.tsx
import './styles/sparta-styles.css'; // Add this line
```
### Option 2: Add to index.tsx
```typescript
// frontend/src/index.tsx
import './styles/sparta-styles.css'; // Add this line
```
### Option 3: Import in Component
```typescript
// 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