Gathering detailed insights and metrics for @vueless/storybook-dark-mode
Gathering detailed insights and metrics for @vueless/storybook-dark-mode
Gathering detailed insights and metrics for @vueless/storybook-dark-mode
Gathering detailed insights and metrics for @vueless/storybook-dark-mode
Storybook v9 addon that lets toggle between dark and light mode 🌗
npm install @vueless/storybook-dark-mode
Typescript
Module System
Min. Node Version
Node Version
NPM Version
TypeScript (87.05%)
JavaScript (12.95%)
Total Downloads
0
Last Day
0
Last Week
0
Last Month
0
Last Year
0
MIT License
10 Stars
24 Commits
1 Forks
1 Watchers
1 Branches
2 Contributors
Updated on Jul 04, 2025
Latest Version
9.0.6
Package Id
@vueless/storybook-dark-mode@9.0.6
Unpacked Size
61.68 kB
Size
11.48 kB
File Count
20
NPM Version
10.9.2
Node Version
22.16.0
Published on
Jul 02, 2025
Cumulative downloads
Total Downloads
Last Day
0%
NaN
Compared to previous day
Last Week
0%
NaN
Compared to previous week
Last Month
0%
NaN
Compared to previous month
Last Year
0%
NaN
Compared to previous year
31
A Storybook v9-optimized addon that enables users to toggle between dark and light modes. For support with earlier Storybook versions, see the original addon.
The project is supported and maintained by the Vueless UI core team. | See the demo 🌗
Install the following npm module:
1npm i -D @vueless/storybook-dark-mode
Then, add following content to .storybook/main.js
1export default { 2 addons: ['@vueless/storybook-dark-mode'] 3};
Configure the dark and light mode by adding the following to your .storybook/preview.js
file:
1import { themes } from 'storybook/theming'; 2 3export const parameters = { 4 darkMode: { 5 // Override the default dark theme 6 dark: { ...themes.dark, appBg: 'black' }, 7 // Override the default light theme 8 light: { ...themes.normal, appBg: 'red' } 9 } 10};
Order of precedence for the initial color scheme:
current
parameter in your storybookOnce the initial color scheme has been set, subsequent reloads will use this value.
To clear the cached color scheme you have to localStorage.clear()
in the chrome console.
1export const parameters = { 2 darkMode: { 3 // Set the initial theme 4 current: 'light' 5 } 6};
This plugin will apply a dark and light class name to the manager. This allows you to easily write dark mode aware theme overrides for the storybook UI.
You can override the classNames applied when switching between light and dark mode using the darkClass
and lightClass
parameters.
1export const parameters = { 2 darkMode: { 3 darkClass: 'lights-out', 4 lightClass: 'lights-on' 5 } 6};
You can also pass an array to apply multiple classes.
1export const parameters = { 2 darkMode: { 3 darkClass: ['lights-out', 'foo'], 4 lightClass: ['lights-on', 'bar'] 5 } 6};
This plugin will apply the dark/light class to the <body>
element of the preview iframe. This can be configured with the classTarget
parameter.
The value will be passed to a querySelector()
inside the iframe.
This is useful if the <body>
is styled according to a parent's class, in that case it can be set to html
.
1export const parameters = { 2 darkMode: { 3 classTarget: 'html' 4 } 5};
This plugin will apply the darkClass
and lightClass
classes to the preview iframe if you turn on the stylePreview
option.
1export const parameters = { 2 darkMode: { 3 stylePreview: true 4 } 5};
If your components use a custom Theme provider, you can integrate it by using the provided hook.
1import { useDarkMode } from '@vueless/storybook-dark-mode'; 2 3// your theme provider 4import ThemeContext from './theme'; 5 6// create a component that uses the dark mode hook 7function ThemeWrapper(props) { 8 // render your custom theme provider 9 return ( 10 <ThemeContext.Provider value={useDarkMode() ? darkTheme : defaultTheme}> 11 {props.children} 12 </ThemeContext.Provider> 13 ); 14} 15 16export const decorators = [renderStory => <ThemeWrapper>{renderStory()}</ThemeWrapper>];
If you want to have you UI's dark mode separate from you components' dark mode, implement this global decorator:
1import { themes } from 'storybook/theming'; 2 3// Add a global decorator that will render a dark background when the 4// "Color Scheme" knob is set to dark 5const knobDecorator = storyFn => { 6 // A knob for color scheme added to every story 7 const colorScheme = select('Color Scheme', ['light', 'dark'], 'light'); 8 9 // Hook your theme provider with some knobs 10 return React.createElement(ThemeProvider, { 11 // A knob for theme added to every story 12 theme: select('Theme', Object.keys(themes), 'default'), 13 colorScheme, 14 children: [ 15 React.createElement('style', { 16 dangerouslySetInnerHTML: { 17 __html: `html { ${ 18 colorScheme === 'dark' ? 'background-color: rgb(35,35,35);' : '' 19 } }` 20 } 21 }), 22 storyFn() 23 ] 24 }); 25}; 26 27export const decorators = [knobDecorator];
You can also listen for the DARK_MODE
event via the addons channel.
1import { useEffect } from 'react'; 2import { addons } from 'storybook/preview-api'; 3import { DARK_MODE_EVENT_NAME } from '@vueless/storybook-dark-mode'; 4 5// your theme provider 6import ThemeContext from './theme'; 7 8// get channel to listen to event emitter 9const channel = addons.getChannel(); 10 11// create a component that listens for the DARK_MODE event 12function ThemeWrapper(props) { 13 // this example uses hook but you can also use class component as well 14 const [isDark, setDark] = useState(false); 15 16 useEffect(() => { 17 // listen to DARK_MODE event 18 channel.on(DARK_MODE_EVENT_NAME, setDark); 19 return () => channel.off(DARK_MODE_EVENT_NAME, setDark); 20 }, [channel, setDark]); 21 22 // render your custom theme provider 23 return ( 24 <ThemeContext.Provider value={isDark ? darkTheme : defaultTheme}> 25 {props.children} 26 </ThemeContext.Provider> 27 ); 28} 29 30export const decorators = [renderStory => <ThemeWrapper>{renderStory()}</ThemeWrapper>];
Since in docs mode, Storybook will not display its toolbar,
You can also trigger the UPDATE_DARK_MODE
event via the addons channel if you want to control that option in docs mode,
By editing your .storybook/preview.js
.
1import React from 'react'; 2import { addons } from 'storybook/preview-api'; 3import { DocsContainer } from '@storybook/addon-docs'; 4import { themes } from 'storybook/theming'; 5 6import { 7 DARK_MODE_EVENT_NAME, 8 UPDATE_DARK_MODE_EVENT_NAME 9} from '@vueless/storybook-dark-mode'; 10 11const channel = addons.getChannel(); 12 13export const parameters = { 14 darkMode: { 15 current: 'light', 16 dark: { ...themes.dark }, 17 light: { ...themes.light } 18 }, 19 docs: { 20 container: props => { 21 const [isDark, setDark] = React.useState(); 22 23 const onChangeHandler = () => { 24 channel.emit(UPDATE_DARK_MODE_EVENT_NAME); 25 }; 26 27 React.useEffect(() => { 28 channel.on(DARK_MODE_EVENT_NAME, setDark); 29 return () => channel.removeListener(DARK_MODE_EVENT_NAME, setDark); 30 }, [channel, setDark]); 31 32 return ( 33 <div> 34 <input type="checkbox" onChange={onChangeHandler} /> 35 <DocsContainer {...props} /> 36 </div> 37 ); 38 } 39 } 40};
No vulnerabilities found.
No security vulnerabilities found.