react-theme-dynplug
v1.0.96
Published
A plugin-based theming system for React applications that separates themes as "style" and "layout". Provides headless theme switching component.
Downloads
2,529
Maintainers
Readme
React Theme Package
A powerful, plugin-based theming system for React applications that separates style (colors, effects) from layout (spacing, sizing).
Features
- Plugin Architecture: Support for different styling libraries (Tailwind, Chakra, etc.) through adapters
- Style vs Layout Separation: Independently control colors/effects and spacing/sizing
- Zero Refactoring: Themes apply globally via CSS variables - no component changes needed
- Headless UI: Fully customizable theme selector component
- TypeScript: Full type safety
- Local Storage: Automatically persists user preferences
Installation
Copy the theme-package directory into your project's src folder.
Quick Start
1. Configure Tailwind (if using Tailwind)
Update your tailwind.config.js to use theme CSS variables:
export default {
theme: {
extend: {
colors: {
primary: 'var(--color-primary)',
secondary: 'var(--color-secondary)',
accent: 'var(--color-accent)',
background: 'var(--color-background)',
surface: 'var(--color-surface)',
text: 'var(--color-text)',
'text-secondary': 'var(--color-text-secondary)',
border: 'var(--color-border)',
},
spacing: {
'theme-xs': 'var(--spacing-xs)',
'theme-sm': 'var(--spacing-sm)',
'theme-md': 'var(--spacing-md)',
'theme-lg': 'var(--spacing-lg)',
'theme-xl': 'var(--spacing-xl)',
'theme-2xl': 'var(--spacing-2xl)',
},
borderRadius: {
'theme-sm': 'var(--radius-sm)',
'theme-md': 'var(--radius-md)',
'theme-lg': 'var(--radius-lg)',
},
fontSize: {
'theme-xs': 'var(--font-size-xs)',
'theme-sm': 'var(--font-size-sm)',
'theme-base': 'var(--font-size-base)',
'theme-lg': 'var(--font-size-lg)',
},
},
},
};2. Wrap Your App
import { ThemeProvider, createTailwindPlugin, styles, layouts } from 'react-theme-dynplug';
const themeConfig = {
styles,
layouts,
defaultStyle: 'ocean',
defaultLayout: 'comfortable'
};
function Root() {
return (
<ThemeProvider config={themeConfig} plugins={[createTailwindPlugin()]}>
<App />
</ThemeProvider>
);
}3. Use Theme Classes
function MyComponent() {
return (
<div className="bg-surface p-theme-md rounded-theme-lg border border-border">
<h1 className="text-theme-2xl text-text">Hello</h1>
<p className="text-theme-base text-text-secondary">World</p>
</div>
);
}4. Add Theme Selector
import { ThemeSelector } from 'react-theme-dynplug';
function ThemeSwitcher() {
return (
<ThemeSelector>
{({ styles, layouts, currentStyle, currentLayout, selectStyle, selectLayout }) => (
<div>
<h3>Styles</h3>
{styles.map(style => (
<button
key={style.id}
onClick={() => selectStyle(style.id)}
className={currentStyle.id === style.id ? 'active' : ''}
>
{style.name}
</button>
))}
<h3>Layouts</h3>
{layouts.map(layout => (
<button
key={layout.id}
onClick={() => selectLayout(layout.id)}
className={currentLayout.id === layout.id ? 'active' : ''}
>
{layout.name}
</button>
))}
</div>
)}
</ThemeSelector>
);
}Creating Custom Themes
Custom Style
import type { ThemeStyle } from 'react-theme-dynplug';
export const myStyle: ThemeStyle = {
id: 'my-style',
name: 'My Custom Style',
colors: {
primary: '#3b82f6',
secondary: '#8b5cf6',
accent: '#ec4899',
background: '#ffffff',
surface: '#f9fafb',
text: '#111827',
text-secondary: '#6b7280',
border: '#e5e7eb',
error: '#ef4444',
success: '#10b981',
warning: '#f59e0b'
},
effects: {
shadow: '0 4px 6px rgba(0,0,0,0.1)',
blur: '8px'
},
animations: {
duration: '200ms',
timing: 'ease-in-out'
}
};Custom Layout
import type { ThemeLayout } from 'react-theme-dynplug';
export const myLayout: ThemeLayout = {
id: 'my-layout',
name: 'My Custom Layout',
spacing: {
xs: '0.25rem',
sm: '0.5rem',
md: '1rem',
lg: '1.5rem',
xl: '2rem',
'2xl': '3rem'
},
sizing: {
container: '1200px',
component: {
xs: '2rem',
sm: '2.5rem',
md: '3rem',
lg: '3.5rem',
xl: '4rem'
}
},
borderRadius: {
sm: '0.25rem',
md: '0.5rem',
lg: '0.75rem',
full: '9999px'
},
typography: {
fontSize: {
xs: '0.75rem',
sm: '0.875rem',
base: '1rem',
lg: '1.125rem',
xl: '1.25rem',
'2xl': '1.5rem',
'3xl': '2rem'
},
lineHeight: {
tight: '1.25',
normal: '1.5',
relaxed: '1.75'
}
}
};Creating Custom Plugins
import type { ThemePlugin } from 'react-theme-dynplug';
export function createMyPlugin(): ThemePlugin {
return {
name: 'my-plugin',
apply: (theme) => {
// Apply theme to your library
console.log('Applying theme:', theme);
},
cleanup: () => {
// Clean up when theme changes
}
};
}API Reference
ThemeProvider Props
config: ThemeConfig - Theme configuration with styles and layoutsplugins: ThemePlugin[] - Array of theme pluginschildren: ReactNode - App contentstorageKey: string - LocalStorage key (default: 'app-theme')
useTheme Hook
Returns:
currentStyle: Current active stylecurrentLayout: Current active layoutavailableStyles: All available stylesavailableLayouts: All available layoutssetStyle(id): Change active stylesetLayout(id): Change active layoutcurrentTheme: Complete current theme object
ThemeSelector Component
Headless component for building custom theme selectors. Uses render props pattern.
Built-in Themes
Styles
- Ocean: Cool blue tones
- Sunset: Warm orange tones
- Forest: Natural green tones
- Midnight: Dark theme with purple accents
Layouts
- Compact: Tight spacing, smaller text
- Comfortable: Balanced spacing and sizing
- Spacious: Generous spacing, larger text
License
MIT
