Advanced Theming System
The Acrobi Design System provides a comprehensive theming platform that supports traditional visual design tokens and advanced dynamic assets including audio, haptic feedback, and motion design tokens.
Overview
The advanced theming system includes:
- Multi-modal Design Tokens: Visual, audio, haptic, and motion tokens
- Theme Inheritance: Create theme variants that extend base themes
- Scoped Theming: Apply different themes to different parts of your application
- Developer Tools: CLI for theme management and build scripts
- Cross-platform Support: Web, iOS, and Android compatibility
Quick Start
Installation
bash
npm install @acrobi/uiBasic Usage
tsx
import { ThemeProvider } from '@acrobi/ui';
import '@acrobi/ui/styles';
function App() {
return (
<ThemeProvider theme="acrobi">
<YourApp />
</ThemeProvider>
);
}Theme Structure
Core Theme Interface
typescript
interface Theme {
name: string;
extends?: string; // For inheritance
tokens: {
colors: Colors;
spacing: Spacing;
fontFamily: FontFamily;
borderRadius: BorderRadius;
};
dynamicAssets?: {
audio: AudioTokens;
haptics: HapticTokens;
motion: MotionTokens;
};
metadata?: {
version: string;
author: string;
description: string;
created: string;
features: {
darkMode: boolean;
highContrast: boolean;
reducedMotion: boolean;
dynamicAssets: boolean;
};
};
}Color Tokens
Colors support both light and dark modes:
typescript
interface Colors {
background: { light: string; dark: string };
foreground: { light: string; dark: string };
primary: { light: string; dark: string };
// ... more colors
}Dynamic Assets
Audio Tokens
typescript
interface AudioTokens {
interactions: {
click: { frequency: number; duration: number; volume: number };
hover: { frequency: number; duration: number; volume: number };
focus: { frequency: number; duration: number; volume: number };
};
feedback: {
success: AudioPattern;
error: AudioPattern;
warning: AudioPattern;
};
// ... more audio tokens
}Haptic Tokens
typescript
interface HapticTokens {
impacts: {
light: { intensity: number; duration: number };
medium: { intensity: number; duration: number };
heavy: { intensity: number; duration: number };
};
notifications: {
success: HapticPattern;
warning: HapticPattern;
error: HapticPattern;
};
// ... more haptic tokens
}Motion Tokens
typescript
interface MotionTokens {
durations: {
fast: string;
normal: string;
slow: string;
};
easings: {
linear: string;
easeIn: string;
easeOut: string;
easeInOut: string;
};
// ... more motion tokens
}Theme Management
CLI Commands
List Available Themes
bash
acrobi theme listCreate New Theme
bash
# Create theme extending acrobi-base
acrobi theme add my-corporate --extends acrobi-base
# Create with custom tokens
acrobi theme add dark-blue --extends acrobi-dark --tokens colors.primary=#1e40afRemove Theme
bash
acrobi theme remove my-corporateBuild System
Build All Themes
bash
npm run build:themesWatch Mode (Development)
bash
npm run build:themes:watchCreate Theme Interactively
bash
npm run create:themeTheme Inheritance
Create efficient theme variants by extending existing themes:
Base Theme Structure
typescript
// themes/base/colors.ts
export const colors: Colors = {
background: { light: '255 255 255', dark: '17 17 17' },
foreground: { light: '17 17 17', dark: '255 255 255' },
primary: { light: '59 130 246', dark: '59 130 246' },
// ... more colors
};Inherited Theme
typescript
// themes/corporate/index.ts
import { acrobiBaseTheme } from '../base';
export const corporateTheme: Theme = {
name: 'corporate',
extends: 'acrobi-base',
tokens: {
...acrobiBaseTheme.tokens,
colors: {
...acrobiBaseTheme.tokens.colors,
primary: { light: '16 185 129', dark: '16 185 129' }, // Override primary
secondary: { light: '245 158 11', dark: '245 158 11' }, // Override secondary
},
},
};Scoped Theming
Apply different themes to different parts of your application:
Basic Scoped Theming
tsx
import { ThemeProvider } from '@acrobi/ui';
function App() {
return (
<div>
{/* Global theme */}
<ThemeProvider theme="acrobi-light">
<Header />
{/* Scoped dark theme for sidebar */}
<ThemeProvider theme="acrobi-dark" enableScoping>
<Sidebar />
</ThemeProvider>
<main>
<Content />
{/* Scoped high contrast theme for accessibility */}
<ThemeProvider theme="acrobi-high-contrast" enableScoping>
<AccessibilityPanel />
</ThemeProvider>
</main>
</ThemeProvider>
</div>
);
}Advanced Scoped Usage
tsx
function Dashboard() {
return (
<div className="dashboard">
{/* Light theme for main content */}
<ThemeProvider theme="acrobi-light" enableScoping scopeId="main-content">
<MainPanel />
</ThemeProvider>
{/* Dark theme for code editor */}
<ThemeProvider theme="acrobi-dark" enableScoping scopeId="code-editor">
<CodeEditor />
</ThemeProvider>
{/* High contrast for accessibility toolbar */}
<ThemeProvider theme="acrobi-high-contrast" enableScoping scopeId="a11y-tools">
<AccessibilityToolbar />
</ThemeProvider>
</div>
);
}Using Themes in Components
Theme Hook
tsx
import { useTheme, useThemeStyles } from '@acrobi/ui';
function CustomButton({ children }: { children: React.ReactNode }) {
const { theme, isDark, toggleDarkMode } = useTheme();
const { getTokenValue, getCSSVariable } = useThemeStyles();
const backgroundColor = getTokenValue('colors.primary.light');
const textColor = getTokenValue('colors.primaryForeground.light');
return (
<button
style={{
backgroundColor: getCSSVariable('color-primary'),
color: getCSSVariable('color-primary-foreground'),
borderRadius: getCSSVariable('radius-md'),
padding: `${getCSSVariable('spacing-sm')} ${getCSSVariable('spacing-md')}`,
}}
onClick={toggleDarkMode}
>
{children} {isDark ? '🌙' : '☀️'}
</button>
);
}CSS Custom Properties
css
.my-component {
background-color: rgb(var(--color-background));
color: rgb(var(--color-foreground));
border: 1px solid rgb(var(--color-border));
border-radius: var(--radius-md);
padding: var(--spacing-md);
font-family: var(--font-sans);
}
.my-component:hover {
background-color: rgb(var(--color-accent));
}
/* Dark mode automatically handled */
.dark .my-component {
/* CSS custom properties automatically update */
}Dynamic Assets Integration
Audio Feedback
tsx
import { useAudioTokens } from '@acrobi/ui';
function InteractiveButton({ children, onClick }) {
const { playAudio } = useAudioTokens();
const handleClick = () => {
playAudio('interactions.click');
onClick?.();
};
const handleHover = () => {
playAudio('interactions.hover');
};
return (
<button
onClick={handleClick}
onMouseEnter={handleHover}
>
{children}
</button>
);
}Haptic Feedback
tsx
import { useHapticTokens } from '@acrobi/ui';
function HapticButton({ children, onClick }) {
const { triggerHaptic } = useHapticTokens();
const handleClick = () => {
triggerHaptic('impacts.medium');
onClick?.();
};
return (
<button onClick={handleClick}>
{children}
</button>
);
}Motion Integration
tsx
import { useMotionTokens } from '@acrobi/ui';
function AnimatedCard({ children }) {
const { getMotionValue, respectsReducedMotion } = useMotionTokens();
const duration = respectsReducedMotion ? '0ms' : getMotionValue('durations.normal');
const easing = getMotionValue('easings.easeInOut');
return (
<div
style={{
transition: respectsReducedMotion ? 'none' : `all ${duration} ${easing}`,
transform: 'translateY(0)',
}}
className="hover:translate-y-[-4px]"
>
{children}
</div>
);
}Accessibility Features
High Contrast Mode
tsx
<ThemeProvider theme="acrobi-high-contrast">
<AccessibleContent />
</ThemeProvider>Reduced Motion Support
tsx
import { useTheme } from '@acrobi/ui';
function AnimatedComponent() {
const { theme } = useTheme();
const prefersReducedMotion = theme?.metadata?.features?.reducedMotion;
return (
<div
className={`transition-all ${prefersReducedMotion ? 'duration-0' : 'duration-300'}`}
>
Content with motion preference respect
</div>
);
}Storybook Integration
The theming system includes comprehensive Storybook integration:
Theme Toolbar
- Multiple Themes: Switch between Light, Dark, High Contrast, and Sepia
- Color Mode Override: Force light or dark independent of theme
- Motion Preferences: Control animation behavior
Asset Testing
Interactive testing for all dynamic assets:
tsx
// Storybook stories automatically include:
export const AudioTesting = {
parameters: {
docs: {
description: {
story: 'Test audio tokens with interactive controls',
},
},
},
};
export const HapticTesting = {
parameters: {
docs: {
description: {
story: 'Test haptic feedback patterns',
},
},
},
};Cross-Platform Considerations
Web Platform
typescript
// Web-specific audio implementation
const webAudio = {
play: (token: AudioToken) => {
const audioContext = new AudioContext();
const oscillator = audioContext.createOscillator();
oscillator.frequency.setValueAtTime(token.frequency, audioContext.currentTime);
oscillator.connect(audioContext.destination);
oscillator.start();
oscillator.stop(audioContext.currentTime + token.duration / 1000);
},
};iOS Platform
typescript
// iOS-specific haptic implementation
const iosHaptics = {
trigger: (token: HapticToken) => {
if (typeof window !== 'undefined' && 'navigator' in window) {
navigator.vibrate?.(token.pattern);
}
},
};Android Platform
typescript
// Android-specific implementation
const androidHaptics = {
trigger: (token: HapticToken) => {
// Android Vibration API implementation
if ('vibrate' in navigator) {
navigator.vibrate(token.duration);
}
},
};Performance Optimization
CSS Custom Properties
The build system generates efficient CSS:
css
[data-theme='acrobi'] {
--color-background: 255 255 255;
--color-foreground: 17 17 17;
/* ... more properties */
}
[data-theme='acrobi'].dark {
--color-background: 17 17 17;
--color-foreground: 255 255 255;
/* Only dark mode overrides */
}Theme Inheritance Optimization
Child themes only include overrides:
css
/* Base theme: 150 properties */
[data-theme='acrobi-base'] { /* ... */ }
/* Child theme: Only 5 overrides */
[data-theme='corporate'] {
--color-primary: 16 185 129;
--color-secondary: 245 158 11;
/* Inherits 145 other properties */
}Troubleshooting
Common Issues
Theme Not Loading
bash
# Check if theme exists
acrobi theme list
# Rebuild themes
npm run build:themesScoped Theming Not Working
tsx
// Ensure enableScoping is true
<ThemeProvider theme="my-theme" enableScoping>
<ScopedContent />
</ThemeProvider>Dynamic Assets Not Playing
tsx
// Check browser support and user interaction
const { canPlayAudio, requestAudioPermission } = useAudioTokens();
if (!canPlayAudio) {
await requestAudioPermission();
}Performance Issues
Large Theme Files
bash
# Use minification for production
npm run build:themes -- --minifyToo Many Theme Switches
tsx
// Debounce theme changes
const debouncedSetTheme = useMemo(
() => debounce(setTheme, 100),
[setTheme]
);Migration Guide
From Basic Theming
tsx
// Before: Basic theme
<div data-theme="dark">
<Content />
</div>
// After: Advanced theme provider
<ThemeProvider theme="acrobi-dark">
<Content />
</ThemeProvider>Adding Dynamic Assets
tsx
// Before: Visual only
const theme = {
colors: { /* ... */ },
spacing: { /* ... */ },
};
// After: Multi-modal
const theme = {
colors: { /* ... */ },
spacing: { /* ... */ },
dynamicAssets: {
audio: { /* ... */ },
haptics: { /* ... */ },
motion: { /* ... */ },
},
};Advanced Usage
Custom Theme Builder
typescript
import { createTheme } from '@acrobi/ui';
const customTheme = createTheme({
name: 'my-brand',
extends: 'acrobi-base',
tokens: {
colors: {
primary: { light: '#FF6B6B', dark: '#FF8E8E' },
secondary: { light: '#4ECDC4', dark: '#6EDDD6' },
},
},
dynamicAssets: {
audio: {
interactions: {
click: { frequency: 800, duration: 100, volume: 0.3 },
},
},
},
});Theme Validation
typescript
import { validateTheme } from '@acrobi/ui';
const isValid = validateTheme(myTheme);
if (!isValid.success) {
console.error('Theme validation failed:', isValid.errors);
}API Reference
Components
ThemeProvider- Root theme provider componentScopedThemeProvider- Scoped theme provider for section-specific theming
Hooks
useTheme()- Access current theme and theme controlsuseThemeStyles()- Theme-aware styling utilitiesuseAudioTokens()- Audio feedback integrationuseHapticTokens()- Haptic feedback integrationuseMotionTokens()- Motion and animation tokens
Utilities
createTheme()- Theme builder utilityvalidateTheme()- Theme validationmergeThemes()- Theme inheritance utilitythemeToCSSProperties()- CSS generation utility
CLI Commands
acrobi theme list- List available themesacrobi theme add <name> --extends <base>- Create new themeacrobi theme remove <name>- Remove themeacrobi theme validate <name>- Validate theme structure
For more examples and advanced usage patterns, see the Storybook documentation and component examples.