@poupe/theme-builder
v0.10.1
Published
Design token management and theme generation system for Poupe UI framework
Downloads
189
Maintainers
Readme
@poupe/theme-builder
Design token management and theme generation system for Material Design 2025 themes with automatic dark mode, CSS variables, and image-based color extraction.
Table of Contents
- Features
- Installation
- Usage
- API Reference
- Color System
- CSS Variables
- Dark Mode
- Integration with Poupe Ecosystem
- Requirements
- License
Features
- 🎨 Material Design 2025 color system with automatic dark themes
- 🌓 Built-in dark mode support with CSS custom properties
- 🖼️ Generate color palettes from images using Material algorithms
- 🔧 Advanced color manipulation utilities (HCT, RGB, HSL, ARGB)
- 📦 Lightweight, tree-shakable API with TypeScript support
- 🧩 CSS variables generation for external customization
- 🎭 Theme scheme variants (vibrant, expressive, content, etc.)
- 🛠️ Server-side utilities for build-time theme generation
- 🎯 Material Design 3 state layer colors for interactive states
Installation
# npm
npm install -D @poupe/theme-builder
# yarn
yarn add -D @poupe/theme-builder
# pnpm
pnpm add -D @poupe/theme-builderUsage
Basic Theme Creation
import { makeTheme } from '@poupe/theme-builder'
// Create Material Design 2025 theme with color roles
const { dark, light } = makeTheme({
primary: '#1976d2',
secondary: '#9c27b0',
tertiary: '#ff4081',
}, 'vibrant', 0.0)
// Access color roles
console.log(light.primary.value) // Primary color in light theme
console.log(dark.onPrimary.value) // Text on primary in dark theme
// Theme with state colors included by default
console.log(light['primary-hover']) // Primary hover state
console.log(dark['on-primary-disabled']) // Disabled text on primary
// Use CSS color-mix() for runtime state color generation
// Fourth parameter accepts additional theme generation options
const runtimeTheme = makeTheme({
primary: '#1976d2',
}, 'content', 0.0, { useColorMix: true })CSS Theme Generation
import { makeCSSTheme } from '@poupe/theme-builder'
// Generate CSS variables for dark/light themes
const cssTheme = makeCSSTheme({
primary: '#6750A4',
secondary: '#958DA5',
error: '#B3261E',
}, {
scheme: 'content',
contrastLevel: 0.5,
prefix: 'md-',
darkMode: ['.dark', 'media'], // Multiple selectors + aliases
lightMode: '.light',
})
// Built-in responsive aliases
makeCSSTheme(colors, {
darkMode: ['dark', 'mobile'], // Uses media queries
lightMode: ['light', 'desktop'] // Now supports arrays too
})
// Advanced selector configuration
const advancedTheme = makeCSSTheme(colors, {
darkMode: ['mobile', '.dark-mode'], // Mobile + custom class
lightMode: ['desktop', '.light-mode'], // Desktop + custom class
})
// Use generated CSS variables
console.log(cssTheme.vars.primary) // '--md-primary'
console.log(cssTheme.styles) // CSS rule objectsTheme from Image
import { fromImageElement } from '@poupe/theme-builder'
// Extract color from image element
async function createImageTheme(imageElement: HTMLImageElement) {
const seedColor = await fromImageElement(imageElement)
const { dark, light } = makeTheme({
primary: seedColor.toHex(),
}, 'expressive')
return { dark, light }
}Color Manipulation
import {
hct, colord, hexString, makeTonalPalette
} from '@poupe/theme-builder/core'
// HCT color space (Hue, Chroma, Tone)
const color = hct('#1976d2')
const lighter = color.withTone(80) // Lighter variant
const muted = color.withChroma(30) // Lower saturation
// Advanced color utilities
const c = colord('#1976d2')
console.log(c.toHsl()) // HSL representation
console.log(c.lighten(0.2).toHex()) // Lightened color
// Format colors
console.log(hexString(lighter)) // Convert to hex string
// Create tonal palette with full tone range (0-100)
const palette = makeTonalPalette('#1976d2')
console.log(palette.tone(50)) // Medium tone
console.log(palette.tone(90)) // Light tone
console.log(palette.tone(10)) // Dark tone
// Harmonize colors to create cohesive palettes
const primary = hct('#1976d2')
const harmonized = makeTonalPalette('#9c27b0', primary)State Layer Colors
Material Design 3 interactive state support:
import {
makeStandardStateVariants,
getStateColorMixParams,
stateLayerOpacities
} from '@poupe/theme-builder'
// Generate state variants for theme colors
const theme = makeTheme({ primary: '#6750A4' })
const stateColors = makeStandardStateVariants(theme.light)
// Access state colors
console.log(stateColors['primary-hover']) // 8% opacity
console.log(stateColors['primary-focus']) // 12% opacity
console.log(stateColors['primary-pressed']) // 12% opacity
console.log(stateColors['on-primary-disabled']) // 38% opacity
// Get CSS color-mix parameters for dynamic theming
const params = getStateColorMixParams('primary', 'hover', '--md-')
// Returns: {
// state: 'hover',
// baseColor: '--md-primary',
// onColor: '--md-on-primary',
// opacityPercent: 8
// }
// Material Design 3 opacity values
console.log(stateLayerOpacities.hover) // 0.08
console.log(stateLayerOpacities.focus) // 0.12
console.log(stateLayerOpacities.pressed) // 0.12
console.log(stateLayerOpacities.dragged) // 0.16
console.log(stateLayerOpacities.disabled) // 0.12
console.log(stateLayerOpacities.onDisabled) // 0.38API Reference
Main Exports
import {
// Theme generation
makeTheme,
makeCSSTheme,
// CSS utilities
assembleCSSColors,
defaultCSSThemeOptions,
// Image extraction
fromImageElement,
// State layer colors
makeStandardStateVariants,
makeCustomStateVariants,
// Color utilities (re-exported from core)
hct,
colord,
hexString,
rgbaString,
} from '@poupe/theme-builder'Core Utilities
Color manipulation and formatting utilities:
import {
// Color types and creation
type Hct,
type HexColor,
hct,
colord,
// Color formatting
hexString,
rgbaString,
// Color conversion
argb,
rgb,
// State layer utilities
stateLayerOpacities,
makeStateLayerColors,
makeStateVariants,
getStateColorMixParams,
// CSS utilities (re-exported)
formatCSSRules,
} from '@poupe/theme-builder/core'Server Utilities
Server-side color processing, validation, and CSS response utilities:
import {
// Parameter processing
getColorParam,
getThemeSchemeParam,
// CSS formatting utilities
stringifyCSSRulesArray,
stringifyCSSRulesArrayStream,
stringifyCSSRulesArrayAsStream,
stringifyCSSRulesArrayAsResponse,
stringifyCSSRulesArrayAsStreamingResponse,
// Color types (re-exported)
type HexColor,
hct,
colord,
} from '@poupe/theme-builder/server'
// Convert to CSS string (no trailing newline)
const cssString = stringifyCSSRulesArray([
{ '.theme': { '--primary': '#6750A4' } }
])
// Convert with camelCase to kebab-case normalization
const normalizedCSS = stringifyCSSRulesArray([
{ fontSize: '16px', backgroundColor: 'blue' }
], { normalizeProperties: true })
// Result: 'font-size: 16px;\nbackground-color: blue;'
// Create ReadableStream (perfect for Cloudflare Workers)
const stream = stringifyCSSRulesArrayAsStream([
{ '.theme': { '--primary': '#6750A4' } }
])
const response = new Response(stream, {
headers: { 'Content-Type': 'text/css' }
})
// Create Response object with headers
const response = stringifyCSSRulesArrayAsResponse([
{ '.theme': { '--primary': '#6750A4' } }
])
// Create streaming Response for large CSS files
const streamingResponse = stringifyCSSRulesArrayAsStreamingResponse([
// Large array of CSS rules
])Color System
Material Design 2025 color roles and theming:
- Primary: Main brand color and variants (primary, primaryDim, onPrimary, primaryContainer, onPrimaryContainer)
- Secondary: Supporting colors (secondary, secondaryDim, onSecondary, secondaryContainer, onSecondaryContainer)
- Tertiary: Accent colors (tertiary, tertiaryDim, onTertiary, tertiaryContainer, onTertiaryContainer)
- Error: Error states (error, onError, errorContainer, onErrorContainer)
- Neutral: Surface and outline colors (surface, onSurface, outline, etc.)
const { dark, light } = makeTheme({
primary: '#6750A4',
secondary: '#958DA5',
tertiary: '#B58392',
neutral: '#938F94',
neutralVariant: '#948F94',
error: '#B3261E',
}, 'content', 0.0)
// Access all color roles
console.log(light.primaryContainer.value) // Primary container color
console.log(dark.onSurfaceVariant.value) // Text on surface variantCSS Variables
Automatic CSS custom property generation:
const cssTheme = makeCSSTheme({
primary: '#6750A4',
}, {
prefix: 'md-', // Variable prefix
darkMode: '.dark', // Dark mode selector
lightMode: '.light', // Light mode selector (optional)
darkSuffix: '-dark', // Dark variable suffix
lightSuffix: '-light', // Light variable suffix
})
// Generated variables
cssTheme.vars.primary // '--md-primary'
cssTheme.vars.onPrimary // '--md-on-primary'
cssTheme.styles // CSS rule objectsDark Mode
Built-in dark mode support with flexible selectors and aliases:
// Class-based dark mode (default)
makeCSSTheme(colors, { darkMode: '.dark' })
// Media query dark mode using built-in alias
makeCSSTheme(colors, { darkMode: 'media' })
// Multiple selectors
makeCSSTheme(colors, { darkMode: ['.dark', '.theme-dark'] })
// Built-in responsive aliases
makeCSSTheme(colors, {
darkMode: ['dark', 'mobile'], // Uses media queries
lightMode: 'light'
})
// Custom selectors
makeCSSTheme(colors, {
darkMode: '[data-theme="dark"]',
lightMode: '[data-theme="light"]'
})
// Disable dark mode
makeCSSTheme(colors, { darkMode: false })Built-in Selector Aliases
The theme builder includes convenient aliases for common media queries:
'media'or'dark'→'@media (prefers-color-scheme: dark)''light'→'@media (prefers-color-scheme: light)''mobile'→'@media (max-width: 768px)''tablet'→'@media (min-width: 769px) and (max-width: 1024px)''desktop'→'@media (min-width: 1025px)'
// Using aliases for responsive theming
const cssTheme = makeCSSTheme(colors, {
darkMode: ['dark', 'tablet'], // Dark mode + tablet screens
lightMode: ['light', 'desktop'], // Light mode + desktop screens
})Integration with Poupe Ecosystem
- @poupe/css - CSS utility library
- @poupe/tailwindcss - TailwindCSS integration
- @poupe/vue - Vue components library
- @poupe/nuxt - Nuxt integration
Requirements
- Node.js >=20.19.1
- TypeScript-friendly environment
License
MIT licensed.
