Theming
Using CSS variables to customize the theme.
Color Tokens
The theme system is built with semantic color tokens that represent specific use cases rather than literal colors. Here are the main color tokens and their use cases:
Base Colors
background
/foreground
: Primary background and text colorscard
/card-foreground
: Used for card components and their contentpopover
/popover-foreground
: For popover, dropdown, dialog, etc.
Interactive Elements
primary
/primary-foreground
: Main brand color, used for primary actionssecondary
/secondary-foreground
: Less prominent actions and elementsmuted
/muted-foreground
: Subdued elements like secondary textaccent
/accent-foreground
: Highlighted or featured elementsdestructive
/destructive-foreground
: Dangerous or destructive actions
Status Colors
danger
/danger-foreground
/danger-border
: Error states and critical alertswarning
/warning-foreground
/warning-border
: Warning messages and alertsinfo
/info-foreground
/info-border
: Informational messagessuccess
/success-foreground
/success-border
: Success states and confirmations
Utility Colors
border
: Default border colorinput
: Form input bordersring
: Focus ring color for interactive elements
Chart Colors
chart-1
throughchart-5
: Predefined colors for data visualizations
Theme Color Mapping
The theme system uses semantic color tokens that map to specific shade values from the Tailwind CSS color palette. Each shade (neutral, gray, slate, stone, zinc) follows the same mapping pattern:
Light Mode Mapping
background
: shade-50 (lightest)foreground
: shade-950 (darkest)card
: shade-100card-foreground
: shade-950popover
: shade-100popover-foreground
: shade-950primary
: shade-950primary-foreground
: shade-50secondary
: shade-200secondary-foreground
: shade-900muted
: shade-200muted-foreground
: shade-600accent
: shade-200accent-foreground
: shade-950destructive
: red-700destructive-foreground
: shade-50border
: shade-300input
: shade-100ring
: shade-400chart-1
: blue-700chart-2
: green-700chart-3
: purple-700chart-4
: orange-700chart-5
: rose-700
Dark Mode Mapping
background
: shade-950 (darkest)foreground
: shade-50 (lightest)card
: shade-900card-foreground
: shade-50popover
: shade-900popover-foreground
: shade-50primary
: shade-50primary-foreground
: shade-950secondary
: shade-800secondary-foreground
: shade-100muted
: shade-800muted-foreground
: shade-400accent
: shade-700accent-foreground
: shade-50destructive
: red-500destructive-foreground
: shade-50border
: shade-700input
: shade-800ring
: shade-500chart-1
: blue-500chart-2
: green-500chart-3
: purple-500chart-4
: orange-500chart-5
: rose-500
Where shade
represents the selected shade (e.g., if using neutral shade: neutral-50, neutral-100, etc.).
The status color system is inspired by Emil Kowalski's Sonner toast library, providing consistent visual feedback across different states.
These status colors remain consistent across all theme shades, ensuring users can always recognize the semantic meaning regardless of the selected color theme.
Why OKLCH?
- Wider Color Gamut: OKLCH can represent a broader range of colors
- Better Color Interpolation: Smoother transitions and animations
- Perceptual Uniformity: More natural-looking color variations
You can read more about OKLCH colors in What are OKLCH colors? by Jakub Krehel.
Customizing Colors
Adding and Using New Colors
To add new colors to your theme:
Add the CSS variables in globals.css
:root {
/* Existing colors */
--custom-color: oklch(62.7% 0.265 303.9);
--custom-color-foreground: oklch(97.7% 0.014 308.299);
}
.dark {
/* Existing dark mode colors */
--custom-color: oklch(62.7% 0.265 303.9);
--custom-color-foreground: oklch(97.7% 0.014 308.299);
}
@theme inline {
/* Existing colors */
--color-custom-color: var(--custom-color);
--color-custom-color-foreground: var(--custom-color-foreground);
}
Use the new colors in your components
<div className="bg-custom-color text-custom-color-foreground">
Custom colored content
</div>