Complete guide to customizing Atomix with CSS-based and JavaScript-based themes. Create custom themes programmatically, switch themes at runtime, and maintain full type safety.
npm install @shohojdhara/atomix1import { ThemeProvider, useTheme, createTheme } from '@shohojdhara/atomix/theme';
2
3// Create a theme
4const myTheme = createTheme({
5 name: 'My Theme',
6 palette: {
7 primary: { main: '#7AFFD7' },
8 secondary: { main: '#FF5733' },
9 },
10});
11
12function App() {
13 return (
14 <ThemeProvider defaultTheme={myTheme}>
15 <YourApp />
16 </ThemeProvider>
17 );
18}
19
20// Use theme in components
21function MyComponent() {
22 const { theme, setTheme, availableThemes } = useTheme();
23
24 return (
25 <div>
26 <p>Current theme: {theme}</p>
27 <button onClick={() => setTheme('dark-theme')}>
28 Switch Theme
29 </button>
30 </div>
31 );
32}1import { ThemeManager, createTheme } from '@shohojdhara/atomix/theme';
2
3const themeManager = new ThemeManager({
4 themes: {
5 'light': { name: 'Light', type: 'css' },
6 'dark': { name: 'Dark', type: 'css' },
7 },
8 defaultTheme: 'light',
9});
10
11// Switch theme
12await themeManager.setTheme('dark');This section is for developers using Atomix in their own projects.
The easiest way to create themes - no build step required:
1import { createTheme, ThemeProvider } from '@shohojdhara/atomix/theme';
2
3const myTheme = createTheme({
4 name: 'My Brand Theme',
5 palette: {
6 primary: { main: '#7AFFD7' },
7 secondary: { main: '#FF5733' },
8 },
9 typography: {
10 fontFamily: 'Inter, sans-serif',
11 },
12});
13
14function App() {
15 return (
16 <ThemeProvider defaultTheme={myTheme}>
17 <YourApp />
18 </ThemeProvider>
19 );
20}Why this is great:
Fastest way to get started:
1import { quickTheme, ThemeProvider } from '@shohojdhara/atomix/theme';
2
3// Create a theme from just brand colors
4const myTheme = quickTheme('My Brand', '#7AFFD7', '#FF5733');
5
6function App() {
7 return (
8 <ThemeProvider defaultTheme={myTheme}>
9 <YourApp />
10 </ThemeProvider>
11 );
12}Use your existing CSS files:
1import { ThemeProvider } from '@shohojdhara/atomix/theme';
2import './my-custom-theme.css';
3
4const themes = {
5 'my-theme': {
6 type: 'css',
7 name: 'My Theme',
8 class: 'my-theme-class',
9 },
10};
11
12function App() {
13 return (
14 <ThemeProvider themes={themes} defaultTheme="my-theme">
15 <YourApp />
16 </ThemeProvider>
17 );
18}You can now customize design tokens using atomix.config.ts:
1// atomix.config.ts (in your project root)
2import { defineConfig } from '@shohojdhara/atomix/config';
3
4export default defineConfig({
5 prefix: 'atomix', // Optional: customize CSS variable prefix
6
7 theme: {
8 extend: {
9 // Customize colors - generates full color scales automatically
10 colors: {
11 primary: { main: '#7AFFD7' }, // Generates primary-1 through primary-10
12 secondary: { main: '#FF5733' },
13 error: { main: '#ef4444' },
14 },
15
16 // Customize typography
17 typography: {
18 fontFamilies: {
19 sans: ['Inter', 'sans-serif'],
20 },
21 fontSizes: {
22 '2xl': '1.5rem',
23 },
24 },
25
26 // Customize spacing
27 spacing: {
28 '18': '4.5rem',
29 '72': '18rem',
30 },
31
32 // Customize border radius
33 borderRadius: {
34 'xl': '0.75rem',
35 },
36 },
37 },
38});sync:tokens, generate:tokens) - These are for library development only.1const brandTheme = createTheme({
2 palette: {
3 primary: { main: '#YOUR_BRAND_COLOR' },
4 },
5});1const darkTheme = createTheme({
2 palette: {
3 background: { default: '#111827' },
4 text: { primary: '#f9fafb' },
5 },
6});1import { createTheme, ThemeProvider, useTheme } from '@shohojdhara/atomix/theme';
2
3const lightTheme = createTheme({
4 name: 'Light',
5 palette: {
6 primary: { main: '#3b82f6' },
7 background: { default: '#ffffff' },
8 },
9});
10
11const darkTheme = createTheme({
12 name: 'Dark',
13 palette: {
14 primary: { main: '#60a5fa' },
15 background: { default: '#111827' },
16 },
17});
18
19function ThemeSwitcher() {
20 const { setTheme } = useTheme();
21
22 return (
23 <div>
24 <button onClick={() => setTheme(lightTheme)}>Light</button>
25 <button onClick={() => setTheme(darkTheme)}>Dark</button>
26 </div>
27 );
28}
29
30function App() {
31 return (
32 <ThemeProvider defaultTheme={lightTheme}>
33 <ThemeSwitcher />
34 <YourApp />
35 </ThemeProvider>
36 );
37}npm install @shohojdhara/atomiximport { createTheme, ThemeProvider } from '@shohojdhara/atomix/theme'const theme = createTheme({ palette: {...} })<ThemeProvider defaultTheme={theme}>var(--atomix-primary)This section is for developers contributing themes to the Atomix library.
Create atomix.config.ts in the project root:
1import { defineConfig } from '@shohojdhara/atomix/config';
2
3export default defineConfig({
4 // CSS variable prefix
5 prefix: 'atomix',
6
7 theme: {
8 // Extend default tokens
9 extend: {
10 colors: {
11 primary: { main: '#7AFFD7' },
12 secondary: { main: '#FF5733' },
13 },
14 spacing: {
15 '18': '4.5rem',
16 },
17 typography: {
18 fontFamilies: {
19 sans: ['Inter', 'sans-serif'],
20 },
21 },
22 },
23
24 // Register themes
25 themes: {
26 'my-theme': {
27 type: 'css',
28 name: 'My Theme',
29 description: 'A custom theme',
30 version: '1.0.0',
31 status: 'stable',
32 },
33 },
34 },
35
36 // Build configuration (internal)
37 build: {
38 output: {
39 directory: 'themes',
40 formats: {
41 expanded: '.css',
42 compressed: '.min.css',
43 },
44 },
45 },
46});1# Sync configuration
2npm run sync:config
3
4# Generate tokens
5npm run sync:tokens
6
7# Validate configuration
8npm run validate:config
9
10# Build themes
11npm run build:themesFor library developers creating SCSS themes:
1src/themes/my-theme/
2├── index.scss
3├── 01-settings/
4│ └── _settings.colors.scss
5├── 06-components/
6│ └── _components.button.scss
7└── 99-utilities/Create index.scss:
1@use '01-settings/index' as *;
2@use '../../styles/02-tools/index' as tools;
3@use '../../styles/03-generic/index' as generic;
4@use '../../styles/04-elements/index' as elements;
5@use '../../styles/05-objects/index' as objects;
6@use '../../styles/06-components/index' as components;
7@use '../../styles/99-utilities/index' as utilities;Override settings:
1// 01-settings/_settings.colors.scss
2@use '../../../styles/01-settings/settings.colors' with (
3 $primary-6: #0ea5e9,
4 $gray-1: #f9fafb,
5);Themes loaded from CSS files, applied via CSS classes:
1// In atomix.config.ts (library developers)
2export default defineConfig({
3 theme: {
4 themes: {
5 'my-theme': {
6 type: 'css',
7 name: 'My Theme',
8 class: 'my-theme-class',
9 cssPath: '/themes/my-theme.css',
10 },
11 },
12 },
13});Themes created programmatically using createTheme():
1import { createTheme } from '@shohojdhara/atomix/theme';
2
3const theme = createTheme({
4 name: 'Custom Theme',
5 palette: {
6 primary: { main: '#7AFFD7' },
7 secondary: { main: '#FF5733' },
8 },
9 typography: {
10 fontFamily: 'Inter, sans-serif',
11 fontSize: 16,
12 },
13});React context provider for theme state:
1<ThemeProvider
2 defaultTheme="my-theme"
3 themes={themes}
4 basePath="/themes"
5 enablePersistence={true}
6>
7 {children}
8</ThemeProvider>React hook for accessing theme context:
1const {
2 theme, // Current theme name
3 activeTheme, // Active theme object (for JS themes)
4 setTheme, // Function to change theme
5 availableThemes, // List of available themes
6 isLoading, // Loading state
7 error, // Error state
8 isThemeLoaded, // Check if theme is loaded
9 preloadTheme, // Preload a theme
10} = useTheme()High-level API for theme management (vanilla JS):
1import { ThemeManager } from '@shohojdhara/atomix/theme';
2
3const themeManager = new ThemeManager({
4 themes: {
5 'light': { name: 'Light', type: 'css' },
6 'dark': { name: 'Dark', type: 'css' },
7 },
8 defaultTheme: 'light',
9 basePath: '/themes',
10 enablePersistence: true,
11});
12
13// Set theme
14await themeManager.setTheme('dark');
15
16// Get current theme
17const currentTheme = themeManager.getTheme();
18
19// Get available themes
20const themes = themeManager.getAvailableThemes();Create a JavaScript theme:
1import { createTheme } from '@shohojdhara/atomix/theme';
2
3const theme = createTheme({
4 name: 'My Theme',
5 palette: {
6 primary: {
7 main: '#7AFFD7',
8 light: '#9AFFE7',
9 dark: '#5ADFC7',
10 },
11 secondary: {
12 main: '#FF5733',
13 },
14 background: {
15 default: '#FAFAFA',
16 paper: '#FFFFFF',
17 },
18 text: {
19 primary: '#111827',
20 secondary: '#6B7280',
21 },
22 },
23 typography: {
24 fontFamily: 'Inter, sans-serif',
25 fontSize: 16,
26 },
27 components: {
28 Button: {
29 styleOverrides: {
30 root: {
31 borderRadius: '8px',
32 },
33 },
34 },
35 },
36});Combine and extend themes:
1import { extendTheme, mergeTheme, composeThemes } from '@shohojdhara/atomix/theme';
2
3// Extend an existing theme
4const extendedTheme = extendTheme(baseTheme, {
5 palette: {
6 primary: { main: '#FF0000' },
7 },
8});
9
10// Merge multiple theme options
11const merged = mergeTheme(
12 { palette: { primary: { main: '#000' } } },
13 { typography: { fontSize: 18 } }
14);
15
16// Compose multiple themes
17const composed = composeThemes(theme1, theme2, theme3);Helper functions for theme management:
1import {
2 quickTheme,
3 createDarkVariant,
4 validateTheme,
5 generateCSSVariables,
6} from '@shohojdhara/atomix/theme';
7
8// Quick theme from colors
9const theme = quickTheme('My Theme', '#7AFFD7', '#FF5733');
10
11// Create dark variant
12const darkTheme = createDarkVariant(lightTheme);
13
14// Validate theme
15const result = validateTheme(theme);
16if (!result.valid) {
17 console.error('Errors:', result.errors);
18}
19
20// Generate CSS variables
21const css = generateCSSVariables(theme, {
22 selector: ':root',
23 prefix: 'atomix',
24});React error boundary for theme errors:
1import { ThemeErrorBoundary } from '@shohojdhara/atomix/theme';
2
3<ThemeErrorBoundary
4 fallback={(error, errorInfo) => <CustomErrorUI />}
5 onError={(error, errorInfo) => {
6 // Send to error tracking
7 }}
8>
9 <ThemeProvider>
10 <App />
11 </ThemeProvider>
12</ThemeErrorBoundary>Enable RTL for right-to-left languages:
1import { RTLManager } from '@shohojdhara/atomix/theme';
2
3const rtlManager = new RTLManager({
4 enabled: true,
5 autoDetect: true,
6 locale: 'ar-SA',
7});
8
9// Set direction
10rtlManager.setDirection('rtl');
11
12// Get RTL-aware values
13const margin = rtlManager.getValue('margin-left', 'margin-right');Or with ThemeProvider:
1<ThemeProvider
2 rtl={{
3 enabled: true,
4 autoDetect: true,
5 }}
6>
7 <App />
8</ThemeProvider>The central configuration file for customizing design tokens and registering themes:
1import { defineConfig } from '@shohojdhara/atomix/config';
2
3export default defineConfig({
4 // CSS variable prefix (default: 'atomix')
5 prefix: 'atomix',
6
7 theme: {
8 // Extend default tokens
9 extend: {
10 // Colors - generates full color scales (1-10) automatically
11 colors: {
12 primary: { main: '#3b82f6' }, // Generates:
13 // --atomix-primary-1 through --atomix-primary-10
14 // --atomix-primary (main color)
15 // --atomix-primary-rgb (for transparency)
16 // --atomix-primary-text-emphasis
17 // --atomix-primary-bg-subtle
18 // --atomix-primary-border-subtle
19 // --atomix-primary-hover
20 secondary: { main: '#10b981' },
21 error: { main: '#ef4444' },
22 },
23
24 // Typography customization
25 typography: {
26 fontFamilies: {
27 sans: ['Inter', 'sans-serif'],
28 },
29 fontSizes: {
30 '2xl': '1.5rem',
31 },
32 fontWeights: {
33 bold: 700,
34 },
35 },
36
37 // Spacing customization
38 spacing: {
39 '18': '4.5rem',
40 '72': '18rem',
41 },
42
43 // Border radius customization
44 borderRadius: {
45 'xl': '0.75rem',
46 },
47 },
48
49 // Register themes
50 themes: {
51 'my-theme': {
52 type: 'css',
53 name: 'My Theme',
54 },
55 },
56 },
57});prefix: CSS variable prefix (default: 'atomix')theme.extend: Extend default design tokenstheme.tokens: Override entire token system (advanced)theme.themes: Register CSS or JS themesbuild: Build configuration (internal)runtime: Runtime configuration (internal)From atomix.config.ts, these files are automatically generated:
src/themes/themes.config.js - Build-time theme configurationsrc/styles/03-generic/_generated-root.css - CSS custom properties from configtheme.extend colors, typography, spacing, etc.When you customize colors in theme.extend.colors, the sync script automatically generates:
For each color (e.g., primary: { main: '#3b82f6' }):
--atomix-primary-1 through --atomix-primary-10--atomix-primary (maps to primary-6)--atomix-primary-rgb (for rgba() usage)--atomix-primary-text-emphasis (for text)--atomix-primary-bg-subtle (for backgrounds)--atomix-primary-border-subtle (for borders)--atomix-primary-hover (for hover states)Example Output:
1/* _generated-root.css */
2:root {
3 --atomix-primary-1: #eff6ff;
4 --atomix-primary-2: #dbeafe;
5 --atomix-primary-3: #bfdbfe;
6 --atomix-primary-4: #93c5fd;
7 --atomix-primary-5: #60a5fa;
8 --atomix-primary-6: #3b82f6; /* main */
9 --atomix-primary-7: #2563eb;
10 --atomix-primary-8: #1d4ed8;
11 --atomix-primary-9: #1e40af;
12 --atomix-primary-10: #1e3a8a;
13 --atomix-primary: #3b82f6;
14 --atomix-primary-rgb: 59, 130, 246;
15 --atomix-primary-text-emphasis: #1e40af;
16 --atomix-primary-bg-subtle: rgba(59, 130, 246, 0.1);
17 --atomix-primary-border-subtle: rgba(59, 130, 246, 0.2);
18 --atomix-primary-hover: #2563eb;
19}1# Sync theme configuration (generates themes.config.js and _generated-root.css)
2npm run sync:config
3
4# Generate tokens (alternative token generation)
5npm run sync:tokens
6
7# Validate configuration sync
8npm run validate:config
9
10# Both sync and validate (runs automatically before build)
11npm run prebuildWhat sync:config does:
atomix.config.tsthemes.config.js with theme metadata and configuration_generated-root.css with CSS custom properties from theme.extendThe theme system generates CSS variables you can use in your styles:
1.my-component {
2 background-color: var(--atomix-primary);
3 color: var(--atomix-primary-contrast-text);
4 padding: var(--atomix-spacing-4);
5 border-radius: var(--atomix-border-radius);
6 box-shadow: var(--atomix-box-shadow-md);
7}--atomix-primary, --atomix-secondary, --atomix-error, etc.--atomix-primary-rgb (for transparency)--atomix-primary-1 through --atomix-primary-10--atomix-primary-text-emphasis--atomix-primary-bg-subtle--atomix-primary-border-subtle--atomix-primary-hover--atomix-primary-gradient--atomix-font-sans-serif, --atomix-font-monospace--atomix-font-size-xs through --atomix-font-size-2xl--atomix-font-weight-light through --atomix-font-weight-bold--atomix-line-height-base, --atomix-line-height-sm, --atomix-line-height-lg--atomix-spacing-0 through --atomix-spacing-200--atomix-spacing-1 (4px), --atomix-spacing-2 (8px), --atomix-spacing-4 (16px)--atomix-border-radius, --atomix-border-radius-sm, --atomix-border-radius-md, --atomix-border-radius-lg, --atomix-border-radius-xl--atomix-box-shadow, --atomix-box-shadow-xs, --atomix-box-shadow-sm, --atomix-box-shadow-lg, --atomix-box-shadow-xl--atomix-border-radius, --atomix-border-radius-sm, --atomix-border-radius-lg, --atomix-border-radius-xl, --atomix-border-radius-xxl, --atomix-border-radius-pill--atomix-border-color, --atomix-border-color-translucent--atomix-transition-fast, --atomix-transition-base, --atomix-transition-slow--atomix-z-dropdown, --atomix-z-modal, --atomix-z-tooltip, etc.--atomix-breakpoint-xs, --atomix-breakpoint-sm, etc.--atomix-focus-ring-width, --atomix-focus-ring-offset, --atomix-focus-ring-opacityIndividual theme CSS files can be imported separately:
1// Import a specific theme CSS file
2import '@shohojdhara/atomix/themes/light';
3// or minified version
4import '@shohojdhara/atomix/themes/light.min';Available Theme Imports:
@shohojdhara/atomix/themes/{theme-name} - Expanded CSS@shohojdhara/atomix/themes/{theme-name}.min - Minified CSSIf you've customized tokens via atomix.config.ts, import the generated CSS:
1// Import generated tokens
2import '@shohojdhara/atomix/styles/03-generic/_generated-root.css';Or if using SCSS:
1@import '@shohojdhara/atomix/scss/generic';The generated tokens will be available as CSS custom properties in your application.
Combine and extend themes to create variations:
1import { mergeTheme, extendTheme } from '@shohojdhara/atomix/theme';
2
3// Merge two themes
4const merged = mergeTheme(baseTheme, overrideTheme);
5
6// Extend theme
7const extended = extendTheme(baseTheme, {
8 palette: {
9 primary: { main: '#FF0000' },
10 },
11});Customize component styles per theme:
1const theme = createTheme({
2 components: {
3 Button: {
4 styleOverrides: {
5 root: {
6 borderRadius: '8px',
7 padding: '12px 24px',
8 },
9 },
10 defaultProps: {
11 variant: 'primary',
12 size: 'lg',
13 },
14 },
15 },
16});Enable RTL for right-to-left languages:
1import { RTLManager } from '@shohojdhara/atomix/theme';
2
3const rtlManager = new RTLManager({
4 enabled: true,
5 autoDetect: true,
6 locale: 'ar-SA',
7});
8
9// Set direction
10rtlManager.setDirection('rtl');Generate CSS variables programmatically:
1import { generateCSSVariables } from '@shohojdhara/atomix/theme';
2
3const css = generateCSSVariables(myTheme, {
4 selector: ':root',
5 prefix: 'atomix',
6});
7
8// Inject into DOM
9document.head.appendChild(
10 Object.assign(document.createElement('style'), {
11 textContent: css,
12 })
13);Validate themes during development:
1import { validateTheme } from '@shohojdhara/atomix/theme';
2
3const result = validateTheme(myTheme);
4
5if (!result.valid) {
6 console.error('Theme validation errors:', result.errors);
7}Preview and inspect themes:
1import { ThemePreview, ThemeInspector } from '@shohojdhara/atomix/theme';
2
3// Preview theme
4<ThemePreview
5 theme={myTheme}
6 showPalette={true}
7 showTypography={true}
8/>
9
10// Inspect theme
11<ThemeInspector
12 theme={myTheme}
13 showValidation={true}
14 showCSSVariables={true}
15/>Problem: Theme fails to load
Solutions:
1const themes = themeManager.getAvailableThemes();
2console.log(themes);1themeManager.on('themeError', (error, themeName) => {
2 console.error('Theme error:', error, themeName);
3});Problem: CSS variables not found
Solutions:
_generated-root.css is importedProblem: Generated tokens don't match config
Solutions:
npm run sync:config to regenerateatomix.config.ts syntax is correctsrc/styles/03-generic/_generated-root.css exists and has content_generated-root.css is imported in your stylesProblem: Only 1 CSS variable generated instead of full scale
Solutions:
theme.extend.colors (not theme.tokens.colors){ main: '#3b82f6' } (not just '#3b82f6')npm run sync:config againProblem: Cannot import theme CSS files
Solutions:
npm run build:themesdist/themes/ directory exists@shohojdhara/atomix/themes/lightatomix.config.tsProblem: TypeScript errors with theme types
Solutions:
1import type { Theme, ThemeMetadata } from '@shohojdhara/atomix/theme';1if (isJSTheme(theme)) {
2 // theme is now typed as Theme
3}Problem: Generated files don't match atomix.config.ts
Solution:
1npm run sync:config
2npm run sync:tokens
3npm run validate:configProblem: Prefix changes in config but not in generated files
Solution:
atomix.config.ts has prefix fieldnpm run sync:config && npm run sync:tokensnpm run validate:config1// In browser environments, provide themes directly
2import { ThemeProvider } from '@shohojdhara/atomix/theme';
3
4const themes = {
5 'my-theme': {
6 type: 'css',
7 name: 'My Theme',
8 class: 'my-theme',
9 },
10};
11
12function App() {
13 return (
14 <ThemeProvider
15 themes={themes}
16 defaultTheme="my-theme"
17 basePath="/themes"
18 >
19 <YourApp />
20 </ThemeProvider>
21 );
22}1import React from 'react';
2import {
3 ThemeProvider,
4 ThemeErrorBoundary,
5 useTheme,
6 createTheme,
7} from '@shohojdhara/atomix/theme';
8
9const lightTheme = createTheme({
10 name: 'Light',
11 palette: {
12 primary: { main: '#3b82f6' },
13 background: { default: '#ffffff' },
14 },
15});
16
17const darkTheme = createTheme({
18 name: 'Dark',
19 palette: {
20 primary: { main: '#60a5fa' },
21 background: { default: '#111827' },
22 },
23});
24
25function ThemeSelector() {
26 const { theme, setTheme } = useTheme();
27
28 return (
29 <select value={theme} onChange={(e) => setTheme(e.target.value)}>
30 <option value={lightTheme}>Light</option>
31 <option value={darkTheme}>Dark</option>
32 </select>
33 );
34}
35
36function App() {
37 return (
38 <ThemeErrorBoundary
39 onError={(error, errorInfo) => {
40 console.error('Theme error:', error);
41 }}
42 >
43 <ThemeProvider
44 defaultTheme={lightTheme}
45 enablePersistence={true}
46 >
47 <ThemeSelector />
48 <YourApp />
49 </ThemeProvider>
50 </ThemeErrorBoundary>
51 );
52}1// app/layout.tsx
2import { ThemeProvider } from '@shohojdhara/atomix/theme';
3
4export default function RootLayout({ children }) {
5 return (
6 <html>
7 <body>
8 <ThemeProvider>
9 {children}
10 </ThemeProvider>
11 </body>
12 </html>
13 );
14}✅ Good:
1.component {
2 color: var(--atomix-primary);
3 padding: var(--atomix-spacing-4);
4}❌ Bad: Hardcoded values like color: #3b82f6; or padding: 16px;
Always use ThemeProvider for React applications instead of direct ThemeManager usage.
Always wrap ThemeProvider with error boundary:
1<ThemeErrorBoundary>
2 <ThemeProvider>
3 <App />
4 </ThemeProvider>
5</ThemeErrorBoundary>Use TypeScript types:
1import type { Theme, ThemeMetadata } from '@shohojdhara/atomix/theme';Use the Theme Studio to create and preview themes interactively. Visualize your theme in real-time and export it for use in your application.
Open Theme Studio