ATXP Design System supports multiple themes with easy runtime switching.
light(default) - Primary brand theme from Figma design system (purple/blue primary)dark- Dark mode optimized for low-light environmentsatxp- Professional black primary with blue accentsdbg- Cyan/turquoise primary with modern, fresh aestheticauto- Automatically adapts to system preference (light/dark)
The easiest way to use themes in a React application is with the ThemeProvider:
import { ThemeProvider } from '@atxp/design-system';
import '@atxp/design-system/styles.css';
function App() {
return (
<ThemeProvider defaultTheme="auto" enablePersistence>
<YourApp />
</ThemeProvider>
);
}| Prop | Type | Default | Description |
|---|---|---|---|
defaultTheme |
'light' | 'dark' | 'ocean' | 'forest' | 'auto' |
'auto' |
Initial theme |
storageKey |
string |
'cc-theme' |
localStorage key for persistence |
enablePersistence |
boolean |
true |
Save theme preference to localStorage |
Access and control themes from any component:
import { useTheme } from '@atxp/design-system';
function ThemeToggle() {
const { theme, setTheme, actualTheme } = useTheme();
return (
<div>
<p>Current theme: {actualTheme}</p>
<button onClick={() => setTheme('light')}>Light</button>
<button onClick={() => setTheme('dark')}>Dark</button>
<button onClick={() => setTheme('atxp')}>ATXP</button>
<button onClick={() => setTheme('dbg')}>DBG</button>
<button onClick={() => setTheme('auto')}>Auto</button>
</div>
);
}| Property | Type | Description |
|---|---|---|
theme |
Theme |
Current theme setting (may be 'auto') |
setTheme |
(theme: Theme) => void |
Function to change theme |
actualTheme |
'light' | 'dark' | 'atxp' | 'dbg' |
Resolved theme (never 'auto') |
Set the theme by adding a data-theme attribute to the <html> element:
<!-- Light theme (default) -->
<html>
<!-- Dark theme -->
<html data-theme="dark">
<!-- ATXP theme -->
<html data-theme="atxp">
<!-- DBG theme -->
<html data-theme="dbg">// Set theme
document.documentElement.setAttribute('data-theme', 'dark');
// Get current theme
const theme = document.documentElement.getAttribute('data-theme') || 'light';
// Remove theme (uses auto/system preference)
document.documentElement.removeAttribute('data-theme');
// Listen for system preference changes
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
mediaQuery.addEventListener('change', (e) => {
console.log('System theme changed to:', e.matches ? 'dark' : 'light');
});You can create custom themes by adding CSS with data attribute selectors:
/* custom-theme.css */
[data-theme="custom"] {
/* Base Colors */
--theme-foreground: #1a1a1a;
--theme-background: #ffffff;
--theme-muted: #f5f5f5;
--theme-border: #e0e0e0;
/* Primary Colors */
--theme-primary: #ff6b6b;
--theme-primary-foreground: #ffffff;
/* Secondary Colors */
--theme-secondary: #f0f0f0;
--theme-secondary-foreground: #333333;
/* Semantic Colors */
--theme-destructive: #dc3545;
--theme-destructive-foreground: #ffffff;
--theme-success: #28a745;
--theme-success-background-fill: #d4edda;
--theme-warning: #ffc107;
--theme-warning-foreground: #212529;
--theme-warning-alt: #fd7e14;
--theme-info: #17a2b8;
--theme-info-foreground: #ffffff;
/* Muted Colors */
--theme-muted-foreground: #d0d0d0;
--theme-accent-muted: #e8e8e8;
}import '@atxp/design-system/styles.css';
import './custom-theme.css';<ThemeProvider defaultTheme="custom">
<YourApp />
</ThemeProvider>Or with vanilla JS:
document.documentElement.setAttribute('data-theme', 'custom');All themes must define these CSS custom properties:
--theme-foreground- Main text color--theme-background- Page background color--theme-muted- Muted background color--theme-border- Border color
--theme-primary- Primary brand color--theme-primary-foreground- Text color on primary background
--theme-secondary- Secondary background color--theme-secondary-foreground- Text color on secondary background
--theme-destructive- Error/danger color--theme-destructive-foreground- Text color on destructive background--theme-success- Success color--theme-success-background-fill- Success background color--theme-warning- Warning color (high priority)--theme-warning-foreground- Text color on warning background--theme-warning-alt- Alternative warning color (medium priority)--theme-info- Info/accent color--theme-info-foreground- Text color on info background
--theme-muted-foreground- Subtle text/border color--theme-accent-muted- Subtle accent background color
Use defaultTheme="auto" to respect user's system-level dark mode preference:
<ThemeProvider defaultTheme="auto" />Enable persistence to remember user's theme selection:
<ThemeProvider defaultTheme="auto" enablePersistence />For server-side rendered applications, set the theme before hydration:
<script>
(function() {
const theme = localStorage.getItem('cc-theme');
if (theme && theme !== 'auto') {
document.documentElement.setAttribute('data-theme', theme);
}
})();
</script>When creating custom themes, ensure adequate color contrast:
- Normal text: minimum 4.5:1 contrast ratio
- Large text (18pt+ or 14pt+ bold): minimum 3:1 contrast ratio
- Use tools like WebAIM Contrast Checker
Ensure your UI works correctly in all available themes:
function ThemeTestWrapper({ children }) {
const themes = ['light', 'dark', 'atxp', 'dbg'];
const [index, setIndex] = useState(0);
return (
<ThemeProvider defaultTheme={themes[index]}>
<button onClick={() => setIndex((i) => (i + 1) % themes.length)}>
Current: {themes[index]}
</button>
{children}
</ThemeProvider>
);
}Target specific themes with CSS:
/* Only in dark theme */
[data-theme="dark"] .my-component {
box-shadow: 0 0 10px rgba(255, 255, 255, 0.1);
}
/* Only in ATXP theme */
[data-theme="atxp"] .my-component {
border-width: 2px; /* Professional, defined borders */
}function MyComponent() {
const { actualTheme } = useTheme();
return (
<div>
{actualTheme === 'dark' && <MoonIcon />}
{actualTheme === 'light' && <SunIcon />}
{actualTheme === 'atxp' && <BriefcaseIcon />}
{actualTheme === 'dbg' && <SparklesIcon />}
</div>
);
}You can nest theme providers for different sections:
function App() {
return (
<ThemeProvider defaultTheme="light">
<Header />
{/* Dashboard always uses dark theme */}
<ThemeProvider defaultTheme="dark">
<Dashboard />
</ThemeProvider>
<Footer />
</ThemeProvider>
);
}-
Ensure you've imported the styles:
import '@atxp/design-system/styles.css';
-
Check that ThemeProvider wraps your app:
<ThemeProvider> <App /> </ThemeProvider>
-
Verify data-theme attribute is set:
console.log(document.documentElement.getAttribute('data-theme'));
Add the theme script before React hydration (see "Prevent Flash of Wrong Theme" above).
- Ensure your custom CSS is loaded after the design system styles
- Verify all required CSS variables are defined
- Check browser DevTools to confirm variables are being applied