One reason for this occurrence is that components are displayed within an iframe, and the storybook-dark-mode (SDM) feature only assigns the "dark" class to the body of the main document.
I confirmed this by inspecting and manually adding it. If you have configured darkMode: 'class'
in your tailwind settings, you should observe it functioning as expected when you insert
<body class="dark">
inside the iframe. Consequently, wrapping it with a parent containing "dark" makes it work solely for that specific instance.
Initial Experiment
The question remains on how to extend this class assignment to the body of the iframe. According to SDM documentation, it suggests applying it to both the application and preview window, which does not appear to be happening in my case.
Interestingly, there exists an add-on known as storybook-tailwind-dark-mode (STDM) that appends "dark" to the <html>
tag of the iframed document, offering some functionality; however, it requires a separate button. This enables rendering components in either dark or light mode independently from the application's dark mode setting.
Currently, this method is effective for me, but I am interested in exploring options where both functionalities can be achieved simultaneously.
For what itβs worth, prior to adopting Tailwind, we utilized a ThemeProvider from StyledComponents with useDarkMode()
from SDM to propagate themes downwards to all StyledComponents (a process we are transitioning away from in favor of Tailwind). Finding a way to incorporate this would be beneficial.
Ultimate Solution
The preceding paragraph sparked an idea. Storybook provides decorators, essentially functions returning components. By enclosing our stories with HTML adorned with classes based on useDarkMode()
, we foster the desired outcome.
Shown below is the implementation I settled on, delivering excellent results. A single button administering dark mode, dispensing with the necessity for additional tailwind-specific dependencies, while seamlessly integrating with my existing StyledComponent theming for yet-to-be-migrated components.
.storybook/theme.js
import React from 'react'
import { ThemeProvider } from 'styled-components'
import { themeV2, GlobalStylesV2 } from 'propritary-design-library'
import { useDarkMode } from 'storybook-dark-mode'
import '../src/index.css'
const ThemeDecorator = storyFn => {
const mode = useDarkMode() ? 'dark' : 'light'
return (
<ThemeProvider theme={themeV2(mode)}>
<section className={mode}>
<GlobalStylesV2 />
{storyFn()}
</section>
</ThemeProvider>
)
}
export default ThemeDecorator
.storybook/preview.js
import { addDecorator } from '@storybook/react'
import ThemeDecorator from './theme'
addDecorator(ThemeDecorator)
export const parameters = {
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/,
},
},
}