/** * DSS Unified Storybook Preview * * Single Storybook instance that loads: * - DSS Core components (atoms, molecules, organisms) * - Project-specific stories (templates, pages) * * Toolbar controls: * - Skin: shadcn, material, heroui * - Mode: light/dark */ import { h } from 'preact'; // Import all component CSS from DSS Core const coreStyles = import.meta.glob('../packages/dss-ui/src/atoms/*.css', { eager: true }); // Import design tokens import '../packages/dss-ui/src/primitives/tokens.css'; // Skin CSS variables - generated from skin dictionaries const skinStyles = { shadcn: { '--color-background': 'hsl(0 0% 100%)', '--color-foreground': 'hsl(240 10% 3.9%)', '--color-card': 'hsl(0 0% 100%)', '--color-card-foreground': 'hsl(240 10% 3.9%)', '--color-popover': 'hsl(0 0% 100%)', '--color-popover-foreground': 'hsl(240 10% 3.9%)', '--color-primary': 'hsl(240 5.9% 10%)', '--color-primary-foreground': 'hsl(0 0% 98%)', '--color-secondary': 'hsl(240 4.8% 95.9%)', '--color-secondary-foreground': 'hsl(240 5.9% 10%)', '--color-muted': 'hsl(240 4.8% 95.9%)', '--color-muted-foreground': 'hsl(240 3.8% 46.1%)', '--color-accent': 'hsl(240 4.8% 95.9%)', '--color-accent-foreground': 'hsl(240 5.9% 10%)', '--color-destructive': 'hsl(0 84.2% 60.2%)', '--color-destructive-foreground': 'hsl(0 0% 98%)', '--color-border': 'hsl(240 5.9% 90%)', '--color-input': 'hsl(240 5.9% 90%)', '--color-ring': 'hsl(240 5.9% 10%)', '--radius': '0.5rem', }, material: { '--color-background': 'hsl(0 0% 99%)', '--color-foreground': 'hsl(0 0% 10%)', '--color-card': 'hsl(0 0% 100%)', '--color-card-foreground': 'hsl(0 0% 10%)', '--color-popover': 'hsl(0 0% 100%)', '--color-popover-foreground': 'hsl(0 0% 10%)', '--color-primary': 'hsl(262 80% 50%)', '--color-primary-foreground': 'hsl(0 0% 100%)', '--color-secondary': 'hsl(262 20% 90%)', '--color-secondary-foreground': 'hsl(262 80% 30%)', '--color-muted': 'hsl(0 0% 96%)', '--color-muted-foreground': 'hsl(0 0% 45%)', '--color-accent': 'hsl(262 20% 95%)', '--color-accent-foreground': 'hsl(262 80% 40%)', '--color-destructive': 'hsl(0 75% 42%)', '--color-destructive-foreground': 'hsl(0 0% 100%)', '--color-border': 'hsl(0 0% 88%)', '--color-input': 'hsl(0 0% 88%)', '--color-ring': 'hsl(262 80% 50%)', '--radius': '1rem', }, heroui: { '--color-background': 'hsl(0 0% 100%)', '--color-foreground': 'hsl(240 6% 10%)', '--color-card': 'hsl(0 0% 100%)', '--color-card-foreground': 'hsl(240 6% 10%)', '--color-popover': 'hsl(0 0% 100%)', '--color-popover-foreground': 'hsl(240 6% 10%)', '--color-primary': 'hsl(212 100% 48%)', '--color-primary-foreground': 'hsl(0 0% 100%)', '--color-secondary': 'hsl(270 60% 52%)', '--color-secondary-foreground': 'hsl(0 0% 100%)', '--color-muted': 'hsl(240 5% 96%)', '--color-muted-foreground': 'hsl(240 4% 46%)', '--color-accent': 'hsl(212 100% 95%)', '--color-accent-foreground': 'hsl(212 100% 40%)', '--color-destructive': 'hsl(0 72% 51%)', '--color-destructive-foreground': 'hsl(0 0% 100%)', '--color-border': 'hsl(240 6% 90%)', '--color-input': 'hsl(240 6% 90%)', '--color-ring': 'hsl(212 100% 48%)', '--radius': '0.75rem', }, }; // Dark mode overrides const darkModeStyles = { shadcn: { '--color-background': 'hsl(240 10% 3.9%)', '--color-foreground': 'hsl(0 0% 98%)', '--color-card': 'hsl(240 10% 3.9%)', '--color-card-foreground': 'hsl(0 0% 98%)', '--color-popover': 'hsl(240 10% 3.9%)', '--color-popover-foreground': 'hsl(0 0% 98%)', '--color-primary': 'hsl(0 0% 98%)', '--color-primary-foreground': 'hsl(240 5.9% 10%)', '--color-secondary': 'hsl(240 3.7% 15.9%)', '--color-secondary-foreground': 'hsl(0 0% 98%)', '--color-muted': 'hsl(240 3.7% 15.9%)', '--color-muted-foreground': 'hsl(240 5% 64.9%)', '--color-accent': 'hsl(240 3.7% 15.9%)', '--color-accent-foreground': 'hsl(0 0% 98%)', '--color-destructive': 'hsl(0 62.8% 30.6%)', '--color-destructive-foreground': 'hsl(0 0% 98%)', '--color-border': 'hsl(240 3.7% 15.9%)', '--color-input': 'hsl(240 3.7% 15.9%)', '--color-ring': 'hsl(240 4.9% 83.9%)', }, material: { '--color-background': 'hsl(280 10% 8%)', '--color-foreground': 'hsl(280 5% 90%)', '--color-card': 'hsl(280 10% 12%)', '--color-card-foreground': 'hsl(280 5% 90%)', '--color-popover': 'hsl(280 10% 12%)', '--color-popover-foreground': 'hsl(280 5% 90%)', '--color-primary': 'hsl(262 80% 70%)', '--color-primary-foreground': 'hsl(280 10% 8%)', '--color-secondary': 'hsl(262 20% 25%)', '--color-secondary-foreground': 'hsl(262 50% 85%)', '--color-muted': 'hsl(280 10% 15%)', '--color-muted-foreground': 'hsl(280 5% 60%)', '--color-accent': 'hsl(262 20% 20%)', '--color-accent-foreground': 'hsl(262 80% 80%)', '--color-destructive': 'hsl(0 60% 50%)', '--color-destructive-foreground': 'hsl(0 0% 100%)', '--color-border': 'hsl(280 10% 20%)', '--color-input': 'hsl(280 10% 20%)', '--color-ring': 'hsl(262 80% 70%)', }, heroui: { '--color-background': 'hsl(240 10% 4%)', '--color-foreground': 'hsl(0 0% 95%)', '--color-card': 'hsl(240 10% 8%)', '--color-card-foreground': 'hsl(0 0% 95%)', '--color-popover': 'hsl(240 10% 8%)', '--color-popover-foreground': 'hsl(0 0% 95%)', '--color-primary': 'hsl(212 100% 55%)', '--color-primary-foreground': 'hsl(0 0% 100%)', '--color-secondary': 'hsl(270 60% 60%)', '--color-secondary-foreground': 'hsl(0 0% 100%)', '--color-muted': 'hsl(240 5% 15%)', '--color-muted-foreground': 'hsl(240 4% 60%)', '--color-accent': 'hsl(212 50% 15%)', '--color-accent-foreground': 'hsl(212 100% 70%)', '--color-destructive': 'hsl(0 72% 55%)', '--color-destructive-foreground': 'hsl(0 0% 100%)', '--color-border': 'hsl(240 6% 20%)', '--color-input': 'hsl(240 6% 20%)', '--color-ring': 'hsl(212 100% 55%)', }, }; // Apply theme to document root const applyTheme = (skin, mode) => { const root = document.documentElement; const styles = mode === 'dark' ? { ...skinStyles[skin], ...darkModeStyles[skin] } : skinStyles[skin]; Object.entries(styles).forEach(([prop, value]) => { root.style.setProperty(prop, value); }); // Set background color on body for Storybook canvas document.body.style.backgroundColor = styles['--color-background']; document.body.style.color = styles['--color-foreground']; }; /** @type { import('@storybook/preact').Preview } */ const preview = { globalTypes: { skin: { description: 'Design system skin', defaultValue: 'shadcn', toolbar: { title: 'Skin', icon: 'paintbrush', items: [ { value: 'shadcn', title: 'shadcn/ui (Default)' }, { value: 'material', title: 'Material Design' }, { value: 'heroui', title: 'HeroUI' }, ], dynamicTitle: true, }, }, mode: { description: 'Color mode', defaultValue: 'light', toolbar: { title: 'Mode', icon: 'circlehollow', items: [ { value: 'light', title: 'Light', icon: 'sun' }, { value: 'dark', title: 'Dark', icon: 'moon' }, ], dynamicTitle: true, }, }, }, parameters: { controls: { matchers: { color: /(background|color)$/i, date: /Date$/i, }, }, backgrounds: { disable: true, // Use our custom theme system instead }, options: { storySort: { order: [ '0. Overview', '1. Primitives', '2. Atoms', '3. Molecules', '4. Organisms', '5. Templates', // Project-specific '6. Pages', // Project-specific ], }, }, }, decorators: [ (Story, context) => { const { skin, mode } = context.globals; applyTheme(skin || 'shadcn', mode || 'light'); return h(Story, null); }, ], }; export default preview;