Theming Guide
UI Lab provides a powerful theming system that allows you to customize every aspect of your components to match your brand identity.
Theme Structure
The theme system is built around design tokens that control:
- Colors - Primary, secondary, semantic colors
- Typography - Font families, sizes, weights, line heights
- Spacing - Margins, padding, gaps
- Borders - Radius, widths, styles
- Shadows - Elevation levels
- Motion - Transition durations and easings
Creating a Custom Theme
1. Define Your Design Tokens
// theme.config.js
export const theme = {
colors: {
primary: {
50: '#fef2f2',
100: '#fee2e2',
500: '#ef4444',
900: '#7f1d1d',
},
secondary: {
50: '#f8fafc',
100: '#f1f5f9',
500: '#64748b',
900: '#0f172a',
},
// Semantic colors
success: '#10b981',
warning: '#f59e0b',
error: '#ef4444',
info: '#3b82f6',
},
typography: {
fontFamily: {
sans: ['Inter', 'system-ui', 'sans-serif'],
heading: ['Poppins', 'sans-serif'],
mono: ['Fira Code', 'monospace'],
},
fontSize: {
xs: '0.75rem',
sm: '0.875rem',
base: '1rem',
lg: '1.125rem',
xl: '1.25rem',
'2xl': '1.5rem',
'3xl': '1.875rem',
},
fontWeight: {
normal: '400',
medium: '500',
semibold: '600',
bold: '700',
},
},
spacing: {
xs: '0.25rem',
sm: '0.5rem',
md: '1rem',
lg: '1.5rem',
xl: '2rem',
'2xl': '3rem',
},
borderRadius: {
none: '0',
sm: '0.25rem',
md: '0.5rem',
lg: '0.75rem',
xl: '1rem',
full: '9999px',
},
};
2. Component-Specific Theming
export const componentThemes = {
Button: {
variants: {
primary: {
backgroundColor: 'var(--ui-color-primary-500)',
color: 'white',
'&:hover': {
backgroundColor: 'var(--ui-color-primary-600)',
},
},
secondary: {
backgroundColor: 'var(--ui-color-secondary-100)',
color: 'var(--ui-color-secondary-900)',
'&:hover': {
backgroundColor: 'var(--ui-color-secondary-200)',
},
},
},
sizes: {
small: {
padding: 'var(--ui-spacing-sm) var(--ui-spacing-md)',
fontSize: 'var(--ui-text-sm)',
},
medium: {
padding: 'var(--ui-spacing-md) var(--ui-spacing-lg)',
fontSize: 'var(--ui-text-base)',
},
large: {
padding: 'var(--ui-spacing-lg) var(--ui-spacing-xl)',
fontSize: 'var(--ui-text-lg)',
},
},
},
};
Dark Mode Theming
Automatic Dark Mode
export const darkTheme = {
colors: {
primary: {
50: '#1e1b4b',
100: '#312e81',
500: '#6366f1',
900: '#e0e7ff',
},
background: {
primary: '#0f172a',
secondary: '#1e293b',
tertiary: '#334155',
},
text: {
primary: '#f8fafc',
secondary: '#cbd5e1',
tertiary: '#94a3b8',
},
},
};
Manual Dark Mode Toggle
// Toggle between light and dark themes
const toggleTheme = () => {
document.documentElement.classList.toggle('dark');
// Store preference
localStorage.setItem(
'theme',
document.documentElement.classList.contains('dark') ? 'dark' : 'light'
);
};
CSS Custom Properties
UI Lab generates CSS custom properties for runtime theming:
:root {
/* Colors */
--ui-color-primary-50: #fef2f2;
--ui-color-primary-500: #ef4444;
--ui-color-primary-900: #7f1d1d;
/* Typography */
--ui-font-sans: 'Inter', system-ui, sans-serif;
--ui-text-base: 1rem;
--ui-font-medium: 500;
/* Spacing */
--ui-spacing-sm: 0.5rem;
--ui-spacing-md: 1rem;
--ui-spacing-lg: 1.5rem;
/* Borders */
--ui-radius-md: 0.5rem;
--ui-border-width: 1px;
/* Shadows */
--ui-shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05);
--ui-shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1);
}
/* Dark mode overrides */
.dark {
--ui-color-primary-500: #6366f1;
--ui-color-background: #0f172a;
--ui-color-text: #f8fafc;
}
Theme Application
Runtime Theme Changes
// Change theme colors dynamically
const changeTheme = (newColors) => {
Object.entries(newColors).forEach(([key, value]) => {
document.documentElement.style.setProperty(`--ui-color-${key}`, value);
});
};
// Example usage
changeTheme({
'primary-500': '#8b5cf6',
'secondary-500': '#06b6d4',
});
Component-Level Customization
// Override specific component styles
<Button
className="custom-button"
style={{
'--ui-button-bg': '#ff6b35',
'--ui-button-text': 'white',
'--ui-button-radius': '20px',
}}
>
Custom Styled Button
</Button>
Best Practices
- Start with Design Tokens - Define your color palette, typography scale, and spacing system first
- Use Semantic Naming - Name colors by their purpose (primary, danger) rather than their appearance (red, blue)
- Test in Both Modes - Always test your theme in both light and dark modes
- Maintain Contrast - Ensure sufficient color contrast for accessibility
- Document Your Theme - Keep a style guide documenting your design decisions
Examples
Brand Theme Example
// Spotify-inspired theme
export const spotifyTheme = {
colors: {
primary: {
500: '#1db954', // Spotify green
},
secondary: {
500: '#191414', // Dark gray
},
background: {
primary: '#121212',
secondary: '#181818',
},
},
borderRadius: {
md: '8px',
lg: '12px',
},
};
Ready to implement your custom theme? Check out our advanced customization guide for more details!