hipstersmoothie / storybook-dark-mode

A storybook addon that lets your users toggle between dark and light mode.
MIT License
435 stars 56 forks source link

Docs is always in light mode #180

Open thany opened 2 years ago

thany commented 2 years ago

All docs as rendered by addon-docs, an official essentials-addon mind you, are always in light mode. No specific configuration has been added to colour anything - it just renders in light mode no matter what.

seedy commented 2 years ago

Trying to upgrade storybook on our repo (https://github.com/traefik/faency), which is publicly accessible here: https://traefik.github.io/faency/

I notice the following:

image

frassinier commented 2 years ago

Here is a workaround by editing your preview.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 } from 'storybook-dark-mode';

const channel = addons.getChannel();

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

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

+           const { id: storyId, storyById } = props.context;
+           const {
+               parameters: { docs = {} },
+           } = storyById(storyId);
+           docs.theme = isDark ? themes.dark : themes.light;

            return (
                <DocsContainer {...props} />
            );
        },
    },
};
TUTAMKHAMON commented 2 years ago

For anyone struggling with this, this is what worked best for me (building upon the answer by @frassinier):

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

import { useDarkMode } from 'storybook-dark-mode'

export const parameters = {
    docs: {
        container: (props) => {
            const isDark = useDarkMode();

            const { id: storyId, storyById } = props.context;
            const {
                parameters: { docs = {} },
            } = storyById(storyId);
            docs.theme = isDark ? themes.dark : themes.light;

            return React.createElement(DocsContainer, props);
        },
    },
};

This should result in a better performing dark mode and removes the need for jsx support on a .js file.

kovjogin commented 1 year ago

Thank you very much @TUTAMKHAMON I use: "storybook": "^7.0.0-rc.5", "storybook-dark-mode": "^2.1.1",

It seems to me that in version 7 api has changed a bit. It's work for me:

import type { Preview } from '@storybook/vue3';
import { DocsContainer } from '@storybook/addon-docs';
import { useDarkMode } from 'storybook-dark-mode';
import { themes } from '@storybook/theming';

const preview: Preview = {
    parameters: {
        docs: {
            container: (context: any) => {
                const isDark = useDarkMode();

                const props = {
                    ...context,
                    theme: isDark ? themes.dark : themes.light,
                };

                return React.createElement(DocsContainer, props);
            },
        },
    },
};
export default preview;
kovjogin commented 1 year ago

Also addon addon-docs adds styles for "preview-loading". Because of what in the dark theme - there are white loading screens.

I didn't find a better solution than to override styles like this:

.sb-preparing-story, .sb-preparing-docs {
  background: transparent !important;
}

.sb-preparing-docs {
  display: none !important;
}

@hipstersmoothie @TUTAMKHAMON FYI

quantizor commented 1 year ago

At least for storybook 7, I think I've managed to partially track down the issue to the useParameter() hook from @storybook/api returning nothing when rendering a docs page

RomanPanaget commented 1 year ago

Thank you very much @TUTAMKHAMON I use: "storybook": "^7.0.0-rc.5", "storybook-dark-mode": "^2.1.1",

It seems to me that in version 7 api has changed a bit. It's work for me:

import type { Preview } from '@storybook/vue3';
import { DocsContainer } from '@storybook/addon-docs';
import { useDarkMode } from 'storybook-dark-mode';
import { themes } from '@storybook/theming';

const preview: Preview = {
  parameters: {
      docs: {
          container: (context: any) => {
              const isDark = useDarkMode();

              const props = {
                  ...context,
                  theme: isDark ? themes.dark : themes.light,
              };

              return React.createElement(DocsContainer, props);
          },
      },
  },
};
export default preview;

This worked for me thank you !

pgrones commented 1 year ago

The workaround above doesn't completely work for me. I'm on "storybook": "7.0.6" and "storybook-dark-mode": "^3.0.0". The first render of the docs is always in light mode. When switching to a different docs page and coming back to the previous one, the theme gets updated (most of the time). I'l fiddle around with it a bit more to see if I can find a solution.

Kinda hard to believe that an official addon doesn't support a basic feature like this.

quantizor commented 1 year ago

It’s not an official addon, and we’re working hard with the storybook team to find a solution.

https://github.com/storybookjs/storybook/issues/21798 https://github.com/storybookjs/storybook/issues/22119#issuecomment-1512399254

The number of breaking changes in v7 are extremely high and it’s been very difficult for addon authors to properly migrate because some functionality disappeared without a replacement.

pgrones commented 1 year ago

I phrased that wrong. I'm not trying to blame you. On the contrary, it's a great addon!

What I meant is that addon-docs is officially maintained by the storybook team, but doesn't support a proper API to toggle the theme. Let's hope the missing APIs are getting replaced in the future.

If you need any information from me to test solutions for this problem just let me know!

tmeasday commented 1 year ago

@pgr3931 can you try in 7.0.7 or later? If you are still seeing a problem can you let me know?

joshuaellis commented 1 year ago

@pgr3931 can you try in 7.0.7 or later? If you are still seeing a problem can you let me know?

I've upgraded today, sorry to tell you still issues :(

tmeasday commented 1 year ago

Can you give a bit more detail @joshuaellis? Ideally with a reproduction I can look at that demonstrates a regression in the addon from 6.5 -> 7.0?

quantizor commented 1 year ago

I was able to get everything working as expected with 7.0.8. Make sure you run yarn dedupe as well to ensure things are on the proper versions.

If you had any custom styling in preview-head.html, note that storybook changed the name of some of the IDs for bits in the UI so CSS selectors might need to be adjusted.

I also added some code in manager-head.html to unset the background color on the preview iframe which helps avoid FOUC.

hipstersmoothie commented 1 year ago

So is there anything to fix here? Will happily merge PRs if there is!

lucasbatiiista commented 1 year ago

The workaround above doesn't completely work for me. I'm on "storybook": "7.0.6" and "storybook-dark-mode": "^3.0.0". The first render of the docs is always in light mode. When switching to a different docs page and coming back to the previous one, the theme gets updated (most of the time). I'l fiddle around with it a bit more to see if I can find a solution.

Kinda hard to believe that an official addon doesn't support a basic feature like this.

For everyone having issues with the first render not applying the theme, this approach worked great for me while using the useDarkMode hook brought in by @TUTAMKHAMON:

docs: {
    container: (props) => {
         const isDark = useDarkMode();
         const currentProps = { ...props };
         currentProps.theme = isDark ? themes.dark : themes.light;
         return React.createElement(DocsContainer, currentProps);
    },
},
TristanBrotherton commented 1 year ago

The workarounds here seem to be for react - can anyone point me in the right direction for getting them to work with Svelte?

d9k commented 9 months ago
docs: {
    container: (props) => {
         const isDark = useDarkMode();
         const currentProps = { ...props };
         currentProps.theme = isDark ? themes.dark : themes.light;
         return React.createElement(DocsContainer, currentProps);
    },
},

https://github.com/hipstersmoothie/storybook-dark-mode/issues/180#issuecomment-1573276315 Works. README should be updated!

hipstersmoothie commented 9 months ago

@d9k wanna make a PR?

silverwind commented 1 month ago

Since storybook 8.1.11, it seems the method with useDarkMode inside the docs.container component seems to fail with "Storybook preview hooks can only be called inside decorators and story functions." for me.

unional commented 1 month ago

Created ticket in storybook: https://github.com/storybookjs/storybook/issues/28758