Skip to content

React Integration

BaroCSS integrates seamlessly with React applications, enabling build-free UI generation and real-time styling without any compilation step. Perfect for AI-driven component systems and dynamic user interfaces.

Setup

1. Installation

bash
npm install barocss
# or
yarn add barocss
# or
pnpm add barocss@latest

2. Initialize BaroCSS

jsx
import React, { useEffect } from 'react';
import { BrowserRuntime } from 'barocss/runtime/browser';

function App() {
  useEffect(() => {
    // Initialize BaroCSS runtime
    const runtime = new BrowserRuntime();
    runtime.init();
    
    // Cleanup on unmount
    return () => {
      runtime.destroy();
    };
  }, []);

  return (
    <div className="min-h-screen bg-[#f8fafc]">
      <AIComponentSystem />
    </div>
  );
}

export default App;

AI-Driven Component Generation

Dynamic Component Generator Hook

jsx
import { useState, useCallback, useMemo } from 'react';

function useAIComponentGenerator() {
  const [components, setComponents] = useState([]);
  const [isGenerating, setIsGenerating] = useState(false);

  // Simulate AI component generation
  const generateComponent = useCallback(async (prompt, config = {}) => {
    setIsGenerating(true);
    
    try {
      // This would call your AI service
      const aiResponse = await simulateAIGeneration(prompt, config);
      
      const newComponent = {
        id: Date.now(),
        type: aiResponse.type,
        props: aiResponse.props,
        styles: aiResponse.styles,
        content: aiResponse.content
      };
      
      setComponents(prev => [...prev, newComponent]);
      return newComponent;
    } finally {
      setIsGenerating(false);
    }
  }, []);

  const removeComponent = useCallback((id) => {
    setComponents(prev => prev.filter(comp => comp.id !== id));
  }, []);

  const updateComponent = useCallback((id, updates) => {
    setComponents(prev => 
      prev.map(comp => 
        comp.id === id 
          ? { ...comp, ...updates }
          : comp
      )
    );
  }, []);

  return {
    components,
    generateComponent,
    removeComponent,
    updateComponent,
    isGenerating
  };
}

// Simulate AI generation
async function simulateAIGeneration(prompt, config) {
  // Simulate API delay
  await new Promise(resolve => setTimeout(resolve, 1000));
  
  const componentTypes = {
    'modern card': {
      type: 'card',
      styles: {
        container: `w-[${config.width || 320}px] h-[${config.height || 200}px] bg-gradient-to-br from-[#667eea] to-[#764ba2] rounded-[16px] shadow-[0_8px_32px_rgba(0,0,0,0.3)] p-[24px] backdrop-blur-[10px] border-[1px] border-[rgba(255,255,255,0.2)]`,
        title: 'text-[24px] font-[600] text-white mb-[12px] leading-[1.2]',
        content: 'text-[16px] text-[rgba(255,255,255,0.9)] leading-[1.5]',
        button: 'mt-[16px] px-[20px] py-[8px] bg-[rgba(255,255,255,0.2)] hover:bg-[rgba(255,255,255,0.3)] text-white rounded-[8px] transition-all duration-[200ms] cursor-pointer border-none backdrop-blur-[5px]'
      },
      content: {
        title: 'AI Generated Card',
        description: 'This card was generated using AI with build-free styling.',
        buttonText: 'Learn More'
      }
    },
    'dashboard widget': {
      type: 'widget',
      styles: {
        container: `w-[${config.width || 280}px] h-[${config.height || 160}px] bg-white rounded-[12px] shadow-[0_4px_20px_rgba(0,0,0,0.08)] border-[1px] border-[#e2e8f0] p-[20px] hover:shadow-[0_8px_40px_rgba(0,0,0,0.12)] transition-all duration-[300ms] hover:scale-[1.02]`,
        header: 'flex items-center justify-between mb-[16px]',
        title: 'text-[14px] font-[500] text-[#64748b] uppercase tracking-[0.5px]',
        value: 'text-[28px] font-[700] text-[#1e293b] mb-[8px]',
        trend: 'text-[12px] font-[500] text-[#10b981] flex items-center',
        icon: 'w-[32px] h-[32px] rounded-[8px] bg-[#3b82f6] bg-opacity-[0.1] flex items-center justify-center'
      },
      content: {
        title: 'Total Revenue',
        value: '$45,234',
        trend: '+12.5%',
        icon: '💰'
      }
    }
  };
  
  const matchedType = Object.keys(componentTypes).find(key => 
    prompt.toLowerCase().includes(key)
  );
  
  return componentTypes[matchedType] || componentTypes['modern card'];
}

AI Component Renderer

jsx
function AIComponentRenderer({ component, onUpdate, onRemove }) {
  const [isEditing, setIsEditing] = useState(false);
  const [editableProps, setEditableProps] = useState(component.props || {});

  const handleStyleUpdate = useCallback(async (instruction) => {
    // Simulate AI style modification
    const updatedStyles = await simulateStyleUpdate(component.styles, instruction);
    onUpdate(component.id, { styles: updatedStyles });
  }, [component, onUpdate]);

  const renderCard = () => (
    <div className={component.styles.container}>
      <h3 className={component.styles.title}>
        {component.content.title}
      </h3>
      <p className={component.styles.content}>
        {component.content.description}
      </p>
      <button 
        className={component.styles.button}
        onClick={() => handleStyleUpdate('make it more vibrant')}
      >
        {component.content.buttonText}
      </button>
      
      {/* Edit overlay */}
      {isEditing && (
        <div className="absolute top-[8px] right-[8px] flex gap-[4px]">
          <button
            className="w-[24px] h-[24px] bg-[rgba(0,0,0,0.5)] text-white rounded-[4px] text-[12px] cursor-pointer border-none"
            onClick={() => handleStyleUpdate('change colors')}
          >
            🎨
          </button>
          <button
            className="w-[24px] h-[24px] bg-[rgba(255,0,0,0.5)] text-white rounded-[4px] text-[12px] cursor-pointer border-none"
            onClick={() => onRemove(component.id)}
          >
            ×
          </button>
        </div>
      )}
    </div>
  );

  const renderWidget = () => (
    <div className={component.styles.container}>
      <div className={component.styles.header}>
        <h4 className={component.styles.title}>
          {component.content.title}
        </h4>
        <div className={component.styles.icon}>
          {component.content.icon}
        </div>
      </div>
      <div className={component.styles.value}>
        {component.content.value}
      </div>
      <div className={component.styles.trend}>
        <span className="mr-[4px]">↗</span>
        {component.content.trend} from last month
      </div>
    </div>
  );

  return (
    <div 
      className="relative"
      onMouseEnter={() => setIsEditing(true)}
      onMouseLeave={() => setIsEditing(false)}
    >
      {component.type === 'card' && renderCard()}
      {component.type === 'widget' && renderWidget()}
    </div>
  );
}

async function simulateStyleUpdate(currentStyles, instruction) {
  // Simulate AI processing the style update instruction
  const updates = { ...currentStyles };
  
  if (instruction.includes('vibrant')) {
    updates.container = updates.container.replace(
      'from-[#667eea] to-[#764ba2]',
      'from-[#ff6b6b] to-[#4ecdc4]'
    );
  }
  
  if (instruction.includes('change colors')) {
    const colors = ['#ff6b6b', '#4ecdc4', '#45b7d1', '#96ceb4', '#ffd93d'];
    const randomColor = colors[Math.floor(Math.random() * colors.length)];
    
    updates.container = updates.container.replace(
      /from-\[#[a-f0-9]{6}\]/,
      `from-[${randomColor}]`
    );
  }
  
  return updates;
}

Real-time Style Editor

Live Style Modification Hook

jsx
import { useState, useRef, useCallback } from 'react';

function useLiveStyleEditor(initialClassName = '') {
  const [className, setClassName] = useState(initialClassName);
  const elementRef = useRef(null);

  const updateStyle = useCallback((property, value) => {
    // Remove existing classes for this property
    const currentClasses = className.split(' ').filter(cls => {
      const propertyPrefixes = {
        width: /^w-/,
        height: /^h-/,
        padding: /^p[xy]?-/,
        margin: /^m[xy]?-/,
        background: /^bg-/,
        text: /^text-/,
        border: /^border-/,
        rounded: /^rounded-/
      };
      
      const regex = propertyPrefixes[property];
      return regex ? !regex.test(cls) : true;
    });

    // Add new class with arbitrary value
    const newClass = `${property}-[${value}]`;
    const updatedClasses = [...currentClasses, newClass].join(' ');
    
    setClassName(updatedClasses);
  }, [className]);

  const addArbitraryClass = useCallback((arbitraryClass) => {
    setClassName(prev => `${prev} ${arbitraryClass}`.trim());
  }, []);

  const removeClasses = useCallback((classesToRemove) => {
    setClassName(prev => 
      prev.split(' ')
        .filter(cls => !classesToRemove.includes(cls))
        .join(' ')
    );
  }, []);

  const resetStyles = useCallback(() => {
    setClassName(initialClassName);
  }, [initialClassName]);

  return {
    className,
    elementRef,
    updateStyle,
    addArbitraryClass,
    removeClasses,
    resetStyles
  };
}

// Usage example
function EditableComponent({ children, initialClass = '' }) {
  const { className, elementRef, updateStyle, addArbitraryClass } = useLiveStyleEditor(initialClass);
  const [isEditorOpen, setIsEditorOpen] = useState(false);

  const handleQuickStyle = (instruction) => {
    // Parse natural language instructions
    if (instruction.includes('bigger')) {
      updateStyle('text', '24px');
    }
    if (instruction.includes('blue')) {
      updateStyle('bg', '#3b82f6');
    }
    if (instruction.includes('rounded')) {
      updateStyle('rounded', '12px');
    }
    if (instruction.includes('shadow')) {
      addArbitraryClass('shadow-[0_10px_40px_rgba(0,0,0,0.15)]');
    }
  };

  return (
    <div className="relative group">
      <div ref={elementRef} className={className}>
        {children}
      </div>
      
      {/* Style editor overlay */}
      <div className="absolute top-[8px] right-[8px] opacity-0 group-hover:opacity-100 transition-opacity duration-[200ms]">
        <button
          className="px-[8px] py-[4px] bg-[rgba(0,0,0,0.8)] text-white text-[12px] rounded-[4px] cursor-pointer border-none"
          onClick={() => setIsEditorOpen(!isEditorOpen)}
        >
          Edit Styles
        </button>
        
        {isEditorOpen && (
          <div className="absolute top-[32px] right-[0] w-[200px] bg-white rounded-[8px] shadow-[0_10px_40px_rgba(0,0,0,0.15)] p-[12px] border-[1px] border-[#e2e8f0] z-[1000]">
            <div className="space-y-[8px]">
              <button
                className="w-full px-[8px] py-[4px] bg-[#3b82f6] text-white text-[12px] rounded-[4px] cursor-pointer border-none hover:bg-[#2563eb]"
                onClick={() => handleQuickStyle('make it bigger and blue')}
              >
                Make Bigger & Blue
              </button>
              <button
                className="w-full px-[8px] py-[4px] bg-[#10b981] text-white text-[12px] rounded-[4px] cursor-pointer border-none hover:bg-[#059669]"
                onClick={() => handleQuickStyle('add rounded corners and shadow')}
              >
                Add Rounded & Shadow
              </button>
              <input
                type="text"
                placeholder="Custom instruction..."
                className="w-full px-[8px] py-[4px] border-[1px] border-[#d1d5db] rounded-[4px] text-[12px]"
                onKeyPress={(e) => {
                  if (e.key === 'Enter') {
                    handleQuickStyle(e.target.value);
                    e.target.value = '';
                  }
                }}
              />
            </div>
          </div>
        )}
      </div>
    </div>
  );
}

Advanced AI Component System

Complete AI-Driven Dashboard

jsx
import React, { useState, useEffect, useCallback } from 'react';

function AIDashboard() {
  const { components, generateComponent, removeComponent, updateComponent, isGenerating } = useAIComponentGenerator();
  const [selectedTemplate, setSelectedTemplate] = useState('dashboard');

  const templates = {
    dashboard: {
      name: 'Dashboard Layout',
      description: 'Professional dashboard with widgets',
      components: [
        { type: 'dashboard widget', config: { width: 280, height: 160 } },
        { type: 'dashboard widget', config: { width: 280, height: 160 } },
        { type: 'dashboard widget', config: { width: 280, height: 160 } },
      ]
    },
    landing: {
      name: 'Landing Page',
      description: 'Modern landing page components',
      components: [
        { type: 'modern card', config: { width: 400, height: 250 } },
        { type: 'modern card', config: { width: 400, height: 250 } },
      ]
    }
  };

  const generateTemplate = useCallback(async (templateKey) => {
    const template = templates[templateKey];
    
    for (const componentConfig of template.components) {
      await generateComponent(componentConfig.type, componentConfig.config);
    }
  }, [generateComponent]);

  const handleAIPrompt = useCallback(async (prompt) => {
    await generateComponent(prompt, { width: 320, height: 200 });
  }, [generateComponent]);

  return (
    <div className="min-h-screen bg-[#f8fafc] p-[20px]">
      {/* AI Control Panel */}
      <div className="mb-[30px] bg-white rounded-[12px] shadow-[0_4px_20px_rgba(0,0,0,0.08)] p-[24px]">
        <h1 className="text-[24px] font-[700] text-[#1e293b] mb-[20px]">
          AI Component Generator
        </h1>
        
        <div className="flex gap-[16px] mb-[20px]">
          {Object.entries(templates).map(([key, template]) => (
            <button
              key={key}
              className={`px-[16px] py-[8px] rounded-[8px] border-[1px] transition-all duration-[200ms] cursor-pointer ${
                selectedTemplate === key
                  ? 'bg-[#3b82f6] text-white border-[#3b82f6]'
                  : 'bg-white text-[#6b7280] border-[#d1d5db] hover:border-[#3b82f6]'
              }`}
              onClick={() => setSelectedTemplate(key)}
            >
              {template.name}
            </button>
          ))}
        </div>
        
        <div className="flex gap-[12px]">
          <button
            className="px-[20px] py-[10px] bg-[#10b981] text-white rounded-[8px] cursor-pointer border-none hover:bg-[#059669] disabled:opacity-[0.5] disabled:cursor-not-allowed transition-all duration-[200ms]"
            onClick={() => generateTemplate(selectedTemplate)}
            disabled={isGenerating}
          >
            {isGenerating ? 'Generating...' : 'Generate Template'}
          </button>
          
          <AIPromptInput onSubmit={handleAIPrompt} disabled={isGenerating} />
        </div>
      </div>

      {/* Generated Components Grid */}
      <div className="grid grid-cols-[repeat(auto-fit,minmax(300px,1fr))] gap-[20px]">
        {components.map(component => (
          <AIComponentRenderer
            key={component.id}
            component={component}
            onUpdate={updateComponent}
            onRemove={removeComponent}
          />
        ))}
      </div>

      {/* Empty State */}
      {components.length === 0 && !isGenerating && (
        <div className="text-center py-[60px]">
          <div className="text-[48px] mb-[16px]">🤖</div>
          <h3 className="text-[18px] font-[600] text-[#1e293b] mb-[8px]">
            No Components Yet
          </h3>
          <p className="text-[14px] text-[#64748b]">
            Generate your first AI component using the controls above
          </p>
        </div>
      )}
    </div>
  );
}

function AIPromptInput({ onSubmit, disabled }) {
  const [prompt, setPrompt] = useState('');

  const handleSubmit = (e) => {
    e.preventDefault();
    if (prompt.trim() && !disabled) {
      onSubmit(prompt.trim());
      setPrompt('');
    }
  };

  return (
    <form onSubmit={handleSubmit} className="flex gap-[8px] flex-1">
      <input
        type="text"
        value={prompt}
        onChange={(e) => setPrompt(e.target.value)}
        placeholder="Describe the component you want to generate..."
        className="flex-1 px-[12px] py-[10px] border-[1px] border-[#d1d5db] rounded-[8px] text-[14px] focus:border-[#3b82f6] focus:ring-[2px] focus:ring-[rgba(59,130,246,0.2)] outline-none transition-all duration-[200ms]"
        disabled={disabled}
      />
      <button
        type="submit"
        className="px-[20px] py-[10px] bg-[#3b82f6] text-white rounded-[8px] cursor-pointer border-none hover:bg-[#2563eb] disabled:opacity-[0.5] disabled:cursor-not-allowed transition-all duration-[200ms]"
        disabled={disabled || !prompt.trim()}
      >
        Generate
      </button>
    </form>
  );
}

Performance Optimization

Component Memoization for BaroCSS

jsx
import React, { memo, useMemo } from 'react';

// Memoized component that only re-renders when styles actually change
const OptimizedAIComponent = memo(function OptimizedAIComponent({ 
  type, 
  styles, 
  content, 
  onUpdate 
}) {
  // Memoize class strings to prevent unnecessary re-renders
  const memoizedClasses = useMemo(() => ({
    container: styles.container,
    title: styles.title,
    content: styles.content
  }), [styles]);

  // Memoize event handlers
  const handleUpdate = useCallback((instruction) => {
    onUpdate(instruction);
  }, [onUpdate]);

  return (
    <div className={memoizedClasses.container}>
      <h3 className={memoizedClasses.title}>
        {content.title}
      </h3>
      <p className={memoizedClasses.content}>
        {content.description}
      </p>
      <button onClick={() => handleUpdate('refresh styles')}>
        Update Styles
      </button>
    </div>
  );
});

// Custom hook for batching BaroCSS updates
function useBatchedUpdates() {
  const [pendingUpdates, setPendingUpdates] = useState([]);
  const timeoutRef = useRef(null);

  const batchUpdate = useCallback((updateFn) => {
    setPendingUpdates(prev => [...prev, updateFn]);
    
    if (timeoutRef.current) {
      clearTimeout(timeoutRef.current);
    }
    
    timeoutRef.current = setTimeout(() => {
      setPendingUpdates(current => {
        // Execute all pending updates in batch
        current.forEach(update => update());
        return [];
      });
    }, 16); // Next frame
  }, []);

  return batchUpdate;
}

This React integration demonstrates how BaroCSS enables build-free AI-driven component generation with real-time styling, performance optimization, and seamless developer experience.

Released under the MIT License.