@consensys/ui-theme
π§ Note: This package is under active development. While we're working hard to make it production-ready, please be aware that APIs and features may change. We welcome your feedback and contributions as we continue to improve!
π¨ Complex theming made simple
Build sophisticated, dynamic themes with a comprehensive design system that includes colors, spacing, typography, shadows, and animations. Our color system handles nested themes, mode switching, and semantic color mapping with ease.
β¨ Standout Features
π¨ Radix Colors - Built on Radix UI Colors for accessible, consistent color usage with semantic mapping
π― Design Token System - Complete set of pre-configured tokens for colors, spacing, typography, shadows, and animations
π¨ Tailwind Classes - Use familiar Tailwind classes with our pre-configured design tokens
π Mode Switching - Toggle between light and dark modes with simple class changes
π Theme Switching - Switch between different themes (default, oceanBreeze, etc.) with class combinations
π Nested Themes - Create complex theme hierarchies with parent-child relationships and inheritance
π¨ Dynamic Inheritance - Child themes inherit from parent themes while maintaining their own overrides
β‘ Dynamic CSS Variables - Runtime theme customization with smooth transitions and real-time updates
π Quick Start
Installation
pnpm add @consensys/ui-theme
Tailwind Configuration
import { tailwindPreset } from '@consensys/ui-theme';
export default {
presets: [tailwindPreset({
themes: {
default: {
colors: {
neutral: 'gray',
primary: 'blue',
secondary: 'violet',
error: 'red',
warning: 'amber',
success: 'green',
info: 'blue',
}
}
}
})],
};
Simple Usage
<div class="light">
<button class="bg-primary hover:bg-primary-7 text-white px-4 py-2 rounded">
Click me
</button>
</div>
<div class="dark">
<button class="bg-primary hover:bg-primary-7 text-white px-4 py-2 rounded">
Click me
</button>
</div>
π¨ Creating Custom Themes
Create custom themes by mapping semantic colors to different Radix colors:
import { tailwindPreset } from '@consensys/ui-theme';
export default {
presets: [tailwindPreset({
themes: {
default: {
colors: {
neutral: 'gray',
primary: 'blue',
secondary: 'violet',
error: 'red',
warning: 'amber',
success: 'green',
info: 'blue',
}
},
oceanBreeze: {
colors: {
neutral: 'slate',
primary: 'cyan',
secondary: 'blue',
error: 'red',
warning: 'amber',
success: 'grass',
info: 'blue',
}
}
}
})],
};
Then use your custom theme with the appropriate mode class:
<div class="oceanBreeze light">
<button class="bg-primary hover:bg-primary-7 text-white">
Ocean Breeze Button
</button>
<p class="text-primary-11">Text using primary color</p>
<div class="bg-primary-a5">Semi-transparent background</div>
</div>
<div class="oceanBreeze dark">
<button class="bg-primary hover:bg-primary-7 text-white">
Ocean Breeze Button
</button>
<p class="text-primary-11">Text using primary color</p>
<div class="bg-primary-a5">Semi-transparent background</div>
</div>
Nested Themes
Create different theme zones within your application:
<div class="light">
<main>
<button class="bg-primary">Default Theme Button</button>
</main>
<div class="oceanBreeze dark">
<button class="bg-primary">Ocean Breeze Dark Button</button>
</div>
<div class="sunset light">
<button class="bg-primary">Sunset Theme Light Button</button>
</div>
</div>
π― Design Tokens
The theme package provides a complete set of design tokens through the Tailwind preset. These tokens are carefully crafted to work together and maintain consistency across your application:
import { tailwindPreset } from '@consensys/ui-theme';
export default {
presets: [tailwindPreset({
themes: {
}
})],
};
The preset includes:
- Colors: Semantic color system built on Radix UI Colors
- Spacing: Consistent spacing scale from 0 to 40rem
- Typography:
- Font families (Inter, Roboto, Libre Franklin)
- Font sizes with line heights and weights
- Heading styles (h1-h6)
- Text styles (xl, lg, base, sm, xs)
- Shadows: Theme-aware shadow tokens
- Animations: Pre-configured animations and keyframes
- Border Radius: Consistent border radius scale
For detailed configuration options, see the Tailwind preset source.
π§ How It Works
Radix Color Foundation
CUI's color system is built on top of Radix UI Colors, providing a robust foundation for accessible and consistent color usage. Each color in our system follows Radix's 12-step scale:
1 - Lightest
2 - Very Light
3 - Light
4 - Light-Medium
5 - Medium-Light
6 - Medium (DEFAULT)
7 - Medium-Dark
8 - Dark-Medium
9 - Dark
10 - Very Dark
11 - Darkest
12 - Alpha variants
Each Radix color comes in four variants:
- Base color (e.g.,
blue
)
- Dark mode color (e.g.,
blueDark
)
- Alpha color (e.g.,
blueA
)
- Dark mode alpha color (e.g.,
blueDarkA
)
Semantic Color Mapping
neutral | Base UI elements, text, borders | gray |
primary | Main actions, brand identity | blue |
secondary | Alternative actions, accents | violet |
error | Error states, destructive actions | red |
warning | Warning states, cautionary actions | amber |
success | Success states, positive actions | green |
info | Information states, neutral actions | blue |
When you map a semantic color to a Radix color, CUI automatically generates all necessary variants:
- Light mode colors (1-12 steps)
- Dark mode colors (1-12 steps)
- Alpha variants for both modes
- CSS variables namespaced to the current theme and mode
Generated CSS Structure
The system generates CSS variables for each theme and mode combination:
.light {
--color-neutral-1: var(--radix-gray-1);
--color-neutral-a1: var(--radix-gray-a1);
--color-primary-1: var(--radix-blue-1);
--color-primary-a1: var(--radix-blue-a1);
}
.dark {
--color-neutral-1: var(--radix-gray-dark-1);
--color-neutral-a1: var(--radix-gray-dark-a1);
--color-primary-1: var(--radix-blue-dark-1);
--color-primary-a1: var(--radix-blue-dark-a1);
}
.oceanBreeze.light {
--color-neutral-1: var(--radix-slate-1);
--color-neutral-a1: var(--radix-slate-a1);
--color-primary-1: var(--radix-cyan-1);
--color-primary-a1: var(--radix-cyan-a1);
}
.oceanBreeze.dark {
--color-neutral-1: var(--radix-slate-dark-1);
--color-neutral-a1: var(--radix-slate-dark-a1);
--color-primary-1: var(--radix-cyan-dark-1);
--color-primary-a1: var(--radix-cyan-dark-a1);
}
These CSS variables are automatically mapped to Tailwind classes:
<div class="light">
<div class="bg-primary-1">Lightest primary color</div>
<div class="text-neutral-1">Lightest neutral color</div>
<div class="bg-primary-a1">Semi-transparent primary color</div>
<div class="text-neutral-a1">Semi-transparent neutral color</div>
</div>
<div class="oceanBreeze light">
<div class="bg-primary-1">Ocean Breeze lightest primary</div>
<div class="bg-primary-a1">Ocean Breeze transparent primary</div>
</div>
<div class="light">
<div class="bg-primary-1">Default theme</div>
<div class="oceanBreeze dark">
<div class="bg-primary-1">Nested Ocean Breeze theme</div>
</div>
</div>
Dynamic CSS Variable Changes
The theme system supports dynamic changes to CSS variables at runtime, enabling smooth transitions between themes and modes. This is particularly useful for:
- Theme switching animations
- User preference changes
- System theme synchronization
- Runtime theme customization
Theme Switching
When switching themes or modes, the system updates CSS variables in real-time:
document.documentElement.classList.remove('light');
document.documentElement.classList.add('dark');
document.documentElement.classList.remove('default');
document.documentElement.classList.add('oceanBreeze');
The CSS variables update automatically, maintaining all color relationships and semantic mappings.
Runtime Customization
You can also customize theme variables at runtime:
document.documentElement.style.setProperty('--color-primary-6', '#custom-color');
document.documentElement.style.setProperty('--color-primary-a6', 'rgba(0, 0, 0, 0.5)');
Smooth Transitions
To enable smooth transitions between theme changes, add transition properties to your CSS:
:root {
--theme-transition-duration: 200ms;
}
* {
transition: background-color var(--theme-transition-duration) ease,
color var(--theme-transition-duration) ease,
border-color var(--theme-transition-duration) ease;
}
This creates a smooth experience when switching between themes or modes.
π€ Contributing
Contributions welcome!
π License
MIT License - Copyright (c) 2024 ConsenSys Mesh