Skip to content

Theme Customization

Sparkle’s theme system is designed to be easily customizable while maintaining consistency and accessibility.

Start by extending the base tokens with your brand colors and design decisions:

import { baseTokens, createTheme } from '@sparkle/theme'
const myCustomTheme = createTheme({
...baseTokens,
colors: {
...baseTokens.colors,
// Override primary brand color
primary: {
50: '#f0f9ff',
100: '#e0f2fe',
200: '#bae6fd',
300: '#7dd3fc',
400: '#38bdf8',
500: '#0ea5e9', // Your brand blue
600: '#0284c7',
700: '#0369a1',
800: '#075985',
900: '#0c4a6e',
950: '#082f49',
},
// Add custom semantic colors
brand: {
light: '#e0f2fe',
main: '#0ea5e9',
dark: '#0369a1',
}
},
spacing: {
...baseTokens.spacing,
// Add custom spacing values
'4xl': '4rem',
'5xl': '5rem',
}
})
import { ThemeProvider } from '@sparkle/theme'
import { myCustomTheme } from './theme'
function App() {
return (
<ThemeProvider theme={myCustomTheme}>
<YourAppContent />
</ThemeProvider>
)
}
import { NativeThemeProvider } from '@sparkle/theme'
import { myCustomTheme } from './theme'
function App() {
return (
<NativeThemeProvider theme={myCustomTheme}>
<YourAppContent />
</NativeThemeProvider>
)
}

Sparkle automatically handles light and dark mode variations:

import { useTheme } from '@sparkle/theme'
function ThemedComponent() {
const { theme, mode, setMode } = useTheme()
// Access current theme values
const backgroundColor = theme.colors.background.primary
const textColor = theme.colors.text.primary
// Toggle theme mode
const toggleMode = () => {
setMode(mode === 'light' ? 'dark' : 'light')
}
return (
<div style={{ backgroundColor, color: textColor }}>
<button onClick={toggleMode}>
Switch to {mode === 'light' ? 'dark' : 'light'} mode
</button>
</div>
)
}

Automatically detect user’s system color scheme preference:

import { useSystemColorScheme } from '@sparkle/theme'
function App() {
const systemScheme = useSystemColorScheme()
return (
<ThemeProvider mode={systemScheme}>
<YourAppContent />
</ThemeProvider>
)
}

Create themed variants for specific components:

const buttonTheme = {
variants: {
primary: {
backgroundColor: 'var(--colors-primary-500)',
color: 'var(--colors-white)',
borderColor: 'var(--colors-primary-500)',
},
secondary: {
backgroundColor: 'var(--colors-secondary-100)',
color: 'var(--colors-secondary-900)',
borderColor: 'var(--colors-secondary-300)',
},
danger: {
backgroundColor: 'var(--colors-error-500)',
color: 'var(--colors-white)',
borderColor: 'var(--colors-error-500)',
}
},
sizes: {
sm: {
padding: 'var(--spacing-xs) var(--spacing-sm)',
fontSize: 'var(--typography-fontSize-sm)',
},
md: {
padding: 'var(--spacing-sm) var(--spacing-md)',
fontSize: 'var(--typography-fontSize-base)',
},
lg: {
padding: 'var(--spacing-md) var(--spacing-lg)',
fontSize: 'var(--typography-fontSize-lg)',
}
}
}

Implement dynamic theme switching with persistence:

import { useTheme, useThemePersistence } from '@sparkle/theme'
function ThemeSwitcher() {
const { mode, setMode } = useTheme()
// Persist theme preference
useThemePersistence('theme-preference')
const themes = [
{ value: 'light', label: 'Light' },
{ value: 'dark', label: 'Dark' },
{ value: 'system', label: 'System' }
]
return (
<select
value={mode}
onChange={(e) => setMode(e.target.value)}
>
{themes.map(theme => (
<option key={theme.value} value={theme.value}>
{theme.label}
</option>
))}
</select>
)
}

Sparkle automatically generates CSS custom properties for all tokens:

/* Available CSS custom properties */
:root {
/* Colors */
--colors-primary-50: #eff6ff;
--colors-primary-500: #3b82f6;
--colors-primary-950: #172554;
/* Spacing */
--spacing-xs: 0.25rem;
--spacing-sm: 0.5rem;
--spacing-md: 1rem;
/* Typography */
--typography-fontSize-base: 1rem;
--typography-fontWeight-medium: 500;
}
/* Dark mode overrides */
[data-theme="dark"] {
--colors-background-primary: #1f2937;
--colors-text-primary: #f9fafb;
}

Use Sparkle tokens with Tailwind CSS:

tailwind.config.js
const { createTailwindTheme } = require('@sparkle/theme')
module.exports = {
theme: {
extend: createTailwindTheme()
}
}
<!-- Use tokens via Tailwind classes -->
<div class="bg-primary-500 text-white p-md rounded-lg">
Themed with Sparkle tokens
</div>

Define responsive token variations:

const responsiveTheme = {
spacing: {
container: {
mobile: '1rem',
tablet: '2rem',
desktop: '3rem',
}
},
typography: {
fontSize: {
heading: {
mobile: '1.5rem',
tablet: '2rem',
desktop: '2.5rem',
}
}
}
}

Use responsive tokens in CSS:

.container {
padding: var(--spacing-container-mobile);
}
@media (min-width: 768px) {
.container {
padding: var(--spacing-container-tablet);
}
}
@media (min-width: 1024px) {
.container {
padding: var(--spacing-container-desktop);
}
}

Validate theme configuration at runtime:

import { validateTheme } from '@sparkle/theme'
const customTheme = {
colors: {
primary: { 500: '#3b82f6' }
}
}
try {
const validatedTheme = validateTheme(customTheme)
console.log('Theme is valid:', validatedTheme)
} catch (error) {
console.error('Theme validation failed:', error.message)
}

Get full TypeScript support for your custom themes:

import type { ThemeConfig } from '@sparkle/theme'
// TypeScript will validate your theme structure
const myTheme: ThemeConfig = {
colors: {
primary: {
500: '#3b82f6' // TypeScript ensures this follows the correct structure
}
}
}

Precompile themes for better performance:

import { compileTheme } from '@sparkle/theme'
// Build time
const compiledTheme = compileTheme(myCustomTheme)
// Runtime - use compiled theme
const App = () => (
<ThemeProvider theme={compiledTheme}>
<App />
</ThemeProvider>
)

Load themes on demand for better initial load performance:

import { lazy } from 'react'
const LazyThemedComponent = lazy(async () => {
const { darkTheme } = await import('./themes/dark')
return { default: () => <ThemedComponent theme={darkTheme} /> }
})
  1. Group related tokens together (colors, spacing, typography)
  2. Use consistent naming across all token categories
  3. Define semantic tokens for common use cases
  4. Document token relationships and dependencies
  1. Minimize runtime calculations by precompiling themes
  2. Use CSS custom properties for dynamic values on web
  3. Cache compiled themes to avoid repeated processing
  4. Lazy load theme variants when not immediately needed
  1. Ensure sufficient contrast ratios for all color combinations
  2. Test themes with accessibility tools and screen readers
  3. Provide high contrast alternatives when needed
  4. Consider motion preferences in animation tokens
  1. Version theme changes using semantic versioning
  2. Document breaking changes and migration paths
  3. Test themes across all supported platforms
  4. Maintain backwards compatibility when possible