Skip to content

Commit

Permalink
Merge pull request #182 from frassinier/master
Browse files Browse the repository at this point in the history
feat: add update_dark_mode event
  • Loading branch information
hipstersmoothie authored Apr 27, 2022
2 parents 3f21431 + 115dde5 commit 108a2e9
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 8 deletions.
59 changes: 54 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ export const parameters = {
darkMode: {
classTarget: 'html'
}
}
};
```

## Story integration
Expand Down Expand Up @@ -141,7 +141,7 @@ import { themes } from '@storybook/theming';

// Add a global decorator that will render a dark background when the
// "Color Scheme" knob is set to dark
const knobDecorator = (storyFn) => {
const knobDecorator = storyFn => {
// A knob for color scheme added to every story
const colorScheme = select('Color Scheme', ['light', 'dark'], 'light');

Expand All @@ -161,7 +161,7 @@ const knobDecorator = (storyFn) => {
storyFn()
]
});
}
};

export const decorators = [knobDecorator];
```
Expand All @@ -173,6 +173,7 @@ You can also listen for the `DARK_MODE` event via the addons channel.
```js
import addons from '@storybook/addons';
import { addDecorator } from '@storybook/react';
import { DARK_MODE_EVENT_NAME } from 'storybook-dark-mode';

// your theme provider
import ThemeContext from './theme';
Expand All @@ -187,8 +188,8 @@ function ThemeWrapper(props) {

useEffect(() => {
// listen to DARK_MODE event
channel.on('DARK_MODE', setDark);
return () => channel.off('DARK_MODE', setDark);
channel.on(DARK_MODE_EVENT_NAME, setDark);
return () => channel.off(DARK_MODE_EVENT_NAME, setDark);
}, [channel, setDark]);

// render your custom theme provider
Expand All @@ -202,6 +203,53 @@ function ThemeWrapper(props) {
export 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`.

```js
import React from 'react';
import addons from '@storybook/addons';
import { DocsContainer } from '@storybook/addon-docs';
import { themes } from '@storybook/theming';

import {
DARK_MODE_EVENT_NAME,
UPDATE_DARK_MODE_EVENT_NAME
} from 'storybook-dark-mode';

const channel = addons.getChannel();

export const parameters = {
darkMode: {
current: 'light',
dark: { ...themes.dark },
light: { ...themes.light }
},
docs: {
container: props => {
const [isDark, setDark] = React.useState();

const onChangeHandler = () => {
channel.emit(UPDATE_DARK_MODE_EVENT_NAME);
};

React.useEffect(() => {
channel.on(DARK_MODE_EVENT_NAME, setDark);
return () => channel.removeListener(DARK_MODE_EVENT_NAME, setDark);
}, [channel, setDark]);

return (
<div>
<input type="checkbox" onChange={onChangeHandler} />
<DocsContainer {...props} />
</div>
);
}
}
};
```

## Contributors ✨

Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
Expand Down Expand Up @@ -237,6 +285,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d

<!-- markdownlint-enable -->
<!-- prettier-ignore-end -->

<!-- ALL-CONTRIBUTORS-LIST:END -->

This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!
17 changes: 14 additions & 3 deletions src/Tool.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ import {
} from '@storybook/core-events';
import { API, useParameter } from '@storybook/api';
import equal from 'fast-deep-equal';
import { DARK_MODE_EVENT_NAME } from './constants';
import {
DARK_MODE_EVENT_NAME,
UPDATE_DARK_MODE_EVENT_NAME
} from './constants';

import Sun from './icons/Sun';
import Moon from './icons/Moon';
Expand Down Expand Up @@ -126,6 +129,8 @@ export const DarkMode = ({ api }: DarkModeProps) => {
const darkModeParams = useParameter<Partial<DarkModeStore>>('darkMode', {});
const { current: defaultMode, stylePreview, ...params } = darkModeParams

const channel = api.getChannel();

// Save custom themes on init
const initialMode = React.useMemo(() => store(params).current, [params]);

Expand Down Expand Up @@ -178,8 +183,6 @@ export const DarkMode = ({ api }: DarkModeProps) => {
}, [darkModeParams, renderTheme])

React.useEffect(() => {
const channel = api.getChannel();

channel.on(STORY_CHANGED, renderTheme);
channel.on(SET_STORIES, renderTheme);
channel.on(DOCS_RENDERED, renderTheme);
Expand All @@ -193,6 +196,14 @@ export const DarkMode = ({ api }: DarkModeProps) => {
};
});

React.useEffect(() => {
channel.on(UPDATE_DARK_MODE_EVENT_NAME, updateMode);

return () => {
channel.removeListener(UPDATE_DARK_MODE_EVENT_NAME, updateMode);
};
});

// Storybook's first render doesn't have the global user params loaded so we
// need the effect to run whenever defaultMode is updated
React.useEffect(() => {
Expand Down
1 change: 1 addition & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export const DARK_MODE_EVENT_NAME = 'DARK_MODE';
export const UPDATE_DARK_MODE_EVENT_NAME = 'UPDATE_DARK_MODE';

0 comments on commit 108a2e9

Please sign in to comment.