CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-storybook-dark-mode

Toggle between light and dark mode in Storybook

Pending
Overview
Eval results
Files

react-integration.mddocs/

React Integration

React hook and component integration patterns for accessing and responding to theme changes in Storybook Dark Mode.

Capabilities

useDarkMode Hook

React hook that returns the current dark mode state and automatically updates when the theme changes.

/**
 * Returns the current state of storybook's dark-mode
 * @returns boolean indicating if dark mode is currently active
 */
function useDarkMode(): boolean;

Usage Examples:

import React from 'react';
import { useDarkMode } from 'storybook-dark-mode';

// Basic theme-aware component
function MyComponent() {
  const isDark = useDarkMode();
  
  return (
    <div style={{ 
      backgroundColor: isDark ? '#333' : '#fff',
      color: isDark ? '#fff' : '#333'
    }}>
      Current theme: {isDark ? 'Dark' : 'Light'}
    </div>
  );
}

// Theme provider wrapper
function ThemeWrapper({ children }) {
  const isDark = useDarkMode();
  
  return (
    <ThemeContext.Provider value={isDark ? darkTheme : lightTheme}>
      {children}
    </ThemeContext.Provider>
  );
}

// Using with Storybook decorators
export const decorators = [
  (renderStory) => (
    <ThemeWrapper>
      {renderStory()}
    </ThemeWrapper>
  )
];

Hook Implementation Details

The hook uses React's useState and useEffect to:

  1. Initialize with current theme state from internal store
  2. Listen for theme change events via Storybook's addon channel
  3. Automatically update component state when theme changes
  4. Clean up event listeners on component unmount

Internal Behavior:

  • Subscribes to DARK_MODE_EVENT_NAME events
  • Manages local state synchronization with global theme state
  • Provides automatic re-rendering when theme changes

Integration Patterns

With Context Providers

import React from 'react';
import { useDarkMode } from 'storybook-dark-mode';
import { ThemeProvider } from 'styled-components';

const darkTheme = { bg: '#333', color: '#fff' };
const lightTheme = { bg: '#fff', color: '#333' };

function StyledThemeWrapper({ children }) {
  const isDark = useDarkMode();
  
  return (
    <ThemeProvider theme={isDark ? darkTheme : lightTheme}>
      {children}
    </ThemeProvider>
  );
}

With CSS Classes

import React from 'react';
import { useDarkMode } from 'storybook-dark-mode';

function ClassBasedThemeWrapper({ children }) {
  const isDark = useDarkMode();
  
  return (
    <div className={isDark ? 'dark-theme' : 'light-theme'}>
      {children}
    </div>
  );
}

With CSS Variables

import React from 'react';
import { useDarkMode } from 'storybook-dark-mode';

function CSSVariableThemeWrapper({ children }) {
  const isDark = useDarkMode();
  
  React.useEffect(() => {
    const root = document.documentElement;
    if (isDark) {
      root.style.setProperty('--bg-color', '#333');
      root.style.setProperty('--text-color', '#fff');
    } else {
      root.style.setProperty('--bg-color', '#fff');
      root.style.setProperty('--text-color', '#333');
    }
  }, [isDark]);
  
  return <>{children}</>;
}

Performance Considerations

  • The hook only re-renders components when the theme actually changes
  • Event listeners are properly cleaned up to prevent memory leaks
  • State updates are batched through React's event system

Install with Tessl CLI

npx tessl i tessl/npm-storybook-dark-mode

docs

configuration.md

event-system.md

index.md

internal-apis.md

react-integration.md

tile.json