Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Storybook 6 docs theming #127

Open
stuarthendren opened this issue Oct 26, 2020 · 36 comments
Open

Storybook 6 docs theming #127

stuarthendren opened this issue Oct 26, 2020 · 36 comments
Labels
help wanted Extra attention is needed

Comments

@stuarthendren
Copy link

Can this be made to also configure the storybook docs theme which is supplied separately in v6.0?

@hipstersmoothie
Copy link
Owner

It could. The last time I looked that wasn't configurable. Would happily accept a PR for this :D

@stuarthendren
Copy link
Author

I had a go at this but I can't see how to make it work.
I can store the relevant docs theme in the globals but I can't see how to provide the theme to the docs. The DocContainer gets the values from the parameters but I don't see any api to set the parameters. I tried using a decorator and setting the parameter value but these seem to only be applied to the stories within the docs - which already worked by the existing mechanism.

@jadenlemmon
Copy link

I would love to see this be possible somehow as well. I'm running into this issue as well. I may have a look.

@stuarthendren
Copy link
Author

In preview.js you can supply a custom container and override the styles using the sbdocs css class(es). This could be a route to making this work:

// preview.js
export const parameters = {
  docs: {
    container: DocsContainerTheme,
  },
}

Then through some styling solution manipulate the theme. As a proof of concept, the following worked to switch the background and color, but would be better to use a theme parameter rather than reconstruct the whole css here:

// DocContainerTheme
import React from 'react'
import { DocsContainer } from '@storybook/addon-docs/blocks'
import { useDarkMode } from 'storybook-dark-mode'
import { makeStyles } from '../../src'

const useStyles = makeStyles({
  override: {
    '& .sbdocs': {
      background: ({ dark }) => (dark ? 'black' : 'white'),
      color: ({ dark }) => (dark ? 'white' : 'black'),
    },
  },
})

export const DocsContainerTheme = ({ children, context }) => {
  const dark = useDarkMode()
  const classes = useStyles({ dark })
  return (
    <div className={classes.override}>
      <DocsContainer context={context}>{children}</DocsContainer>
    </div>
  )
}

@hipstersmoothie
Copy link
Owner

I think official support for this is still waiting on storybookjs/storybook#10523

Without a way to dynamically set params for the docs theme, this plugin can't do much. The approach above seems nice though in the interim

@soullivaneuh
Copy link

soullivaneuh commented Mar 18, 2021

Thanks for the sharing @stuarthendren!

I found a better workaround that will fully respect the used theming without hacking the css by overriding the context using spread operators.

First, create a doc container as the above example:

// .storybook/components/DocContainer.tsx
import React from 'react'
import { DocsContainer as BaseContainer } from '@storybook/addon-docs/blocks'
import { useDarkMode } from 'storybook-dark-mode'
import { themes } from '@storybook/theming';

export const DocsContainer = ({ children, context }) => {
  const dark = useDarkMode()

  return (
    <BaseContainer
      context={{
        ...context,
        parameters: {
          ...context.parameters,
          docs: {
            // This is where the magic happens.
            theme: dark ? themes.dark : themes.light
          },
        },
      }}
    >
      {children}
    </BaseContainer>
  );
}

Then on your preview.js config file:

// .storybook/preview.js
import { DocsContainer } from './components/DocContainer';

export const parameters = {
  docs: {
    container: DocsContainer,
  },
  // Rest of your configuration
};

And voilà! 🎉

UPDATE: Not working since Storybook 6.4. See #127 (comment) or #127 (comment) for 6.4 compatible solution.

@sekoyo
Copy link

sekoyo commented Apr 30, 2021

return (
    <BaseContainer
      context={{
        ...context,
        parameters: {
          ...context.parameters,
          docs: {
            // This is where the magic happens.
            theme: dark ? themes.dark : themes.light
          },
        },
      }}
    >
      {children}
    </BaseContainer>
  );

This is life affirming. Surprised it's not in the docs as I don't consider it to be working properly if everything is dark and Docs are still blindingly white 😅

@hugoattal
Copy link

hugoattal commented May 13, 2021

I'm not using React (but Vue3) and didn't see anything on creating containers in Vue (I'm not even sure it's possible).

So I went with a very simple (but not reactive) solution, adding this in my preview.ts:

export const parameters = {
    /* ... */
    docs: {
        get theme() {
            let isDarkMode = parent.document.body.classList.contains("dark");
            return isDarkMode ? themes.dark : themes.light;
        }
    },
    /* ... */
};

It's not reactive, so you must reload the page. The check is kinda dirty/hacky. But it works for my case, so I thought I might share.

@gsingh1370
Copy link

gsingh1370 commented May 24, 2021

the above solution is working for me for the theme but it stopped showing props table. any ideas?

Error:
Args unsupported. See Args documentation for your framework.
Read the docs

@gazpachu
Copy link

gazpachu commented May 28, 2021

Yeah, same for me:

Screenshot 2021-05-28 at 10 57 44

@soullivaneuh @gsingh1370 @dominictobias have you managed to make the props work?

@gsingh1370
Copy link

@gazpachu use this. Added docs from context

import React from 'react'
import { DocsContainer as BaseContainer } from '@storybook/addon-docs/blocks'
import { useDarkMode } from 'storybook-dark-mode'
import { themes } from '@storybook/theming';

export const DocsContainer = ({ children, context }) => {
const dark = useDarkMode()

return (
<BaseContainer
context={{
...context,
parameters: {
...context.parameters,
docs: {
...context.parameters.docs,
// This is where the magic happens.
theme: dark ? themes.dark : themes.light
},
},
}}
>
{children}

);
}

@gazpachu
Copy link

Thanks, at the end, with lodash/set, the props work fine:

import set from 'lodash/set';
import React, { ReactNode } from 'react';
import { useDarkMode } from 'storybook-dark-mode';

export const DocsContainer = ({
  children,
  context
}: {
  children: ReactNode;
  context: any;
}) => {
  const dark = useDarkMode();
  set(context, 'parameters.docs.theme', dark ? themes.dark : themes.light);
  return <BaseContainer context={context}>{children}</BaseContainer>;
};

@soullivaneuh
Copy link

@gsingh1370 @gazpachu Not tested because I don't use props for my case, but as an alternative as the lodash example, you may use an additional spread operator:

diff --git a/.storybook/components/DocContainer.tsx b/.storybook/components/DocContainer.tsx
index a0fd4b7..d1d775d 100644
--- a/.storybook/components/DocContainer.tsx
+++ b/.storybook/components/DocContainer.tsx
@@ -18,6 +18,7 @@ export const DocsContainer: FC<DocsContainerProps> = ({ children, context }) =>
         parameters: {
           ...parameters,
           docs: {
+            ...parameters.docs,
             theme: dark ? themes.dark : themes.light,
           },
         },

This is surely why you don't have any prop, the docs part is completely overridden on my previous sample.

@soullivaneuh
Copy link

Hmm I just upgraded from 6.4.0-beta.19 and the magic is no longer working, switching back to a "stuck light mode".

Does anyone got the same issue? Do you know if a workaround is possible?

@dartess
Copy link
Contributor

dartess commented Nov 29, 2021

Storybook has released 6.4.

I haven't found a new way to set the theme dynamically. My very, very dirty hack with page refresh looks like this:

import React, { useEffect } from 'react';
import { addParameters } from '@storybook/react';
import { DocsContainer as BaseContainer } from '@storybook/addon-docs';
import { themes } from '@storybook/theming';
import { useDarkMode } from 'storybook-dark-mode';

const isInitialDark = JSON.parse(localStorage.getItem('sb-addon-themes-3') ?? '{}')?.current === 'dark';

addParameters({
  docs: {
    theme: isInitialDark ? themes.dark : themes.light,
  },
});

export const DocsContainer: typeof BaseContainer = (props) => {
  const isDark = useDarkMode();

  useEffect(
    () => {
      if (isInitialDark !== isDark) {
        window.location.reload();
      }
    },
    [isDark],
  )

  return <BaseContainer {...props} />;
};

I think this could potentially lead to endless page reloads. Use at your own risk.

@aaron-a-anderson
Copy link

@dartess , @soullivaneuh after digging through the updates to DocsContainer in 6.4 , was able to get it working this way:

    <BaseContainer
      context={{
        ...context,
        storyById: (id) => {
          const storyContext = context.storyById(id);
          return {
            ...storyContext,
            parameters: {
              ...storyContext?.parameters,
              docs: {
                theme: dark ? themes.dark : themes.light,
              },
            },
          }
        },
      }}
    >

Not sure if this is the intended way, but it's working for me 😄

@acc-nicholas
Copy link

Anyone have a similar issue with the controls addon? I've got everything dark but that portion of the UI.
image

@Kevin-S-Wallace
Copy link

I was able to get both the args table to work correctly with subcomponents and the controls section to show up in dark mode with this:

    <BaseContainer
      context={{
        ...context,
        storyById: (id) => {
          const storyContext = context.storyById(id)
          return {
            ...storyContext,
            parameters: {
              ...storyContext?.parameters,
              docs: {
                ...storyContext?.parameters?.docs,
                theme: dark ? darkTheme : themes.light,
              },
            },
          }
        },
      }}
    >

@kidsamort
Copy link

Мне удалось заставить таблицу аргументов правильно работать с подкомпонентами и разделом управления, чтобы он отображался в темном режиме с помощью этого:

    <BaseContainer
      context={{
        ...context,
        storyById: (id) => {
          const storyContext = context.storyById(id)
          return {
            ...storyContext,
            parameters: {
              ...storyContext?.parameters,
              docs: {
                ...storyContext?.parameters?.docs,
                theme: dark ? darkTheme : themes.light,
              },
            },
          }
        },
      }}
    >

tell me where you used it

@fedek6
Copy link

fedek6 commented Mar 17, 2022

For anyone reading this in 2022. This is full fix description:

  1. Create .storybook/DocsContainer.js
import React from "react";
import { DocsContainer as BaseContainer } from "@storybook/addon-docs/blocks";
import { useDarkMode } from "storybook-dark-mode";
import { themes } from "@storybook/theming";

export const DocsContainer = ({ children, context }) => {
  const dark = useDarkMode();

  return (
    <BaseContainer
      context={{
        ...context,
        storyById: (id) => {
          const storyContext = context.storyById(id);
          return {
            ...storyContext,
            parameters: {
              ...storyContext?.parameters,
              docs: {
                ...storyContext?.parameters?.docs,
                theme: dark ? themes.dark : themes.light,
              },
            },
          };
        },
      }}
    >
      {children}
    </BaseContainer>
  );
};
  1. Edit & tune for your needs: .storybook/preview.js
import React from "react";
import { useDarkMode } from "storybook-dark-mode";
import { themes } from "@storybook/theming";
import { darkTheme } from "@retrolove-games/ui-themes";
import { DocsContainer } from './DocsContainer';

export const parameters = {
  actions: { argTypesRegex: "^on[A-Z].*" },
  controls: {
    matchers: {
      color: /(background|color)$/i,
      date: /Date$/,
    },
  },
  viewMode: "docs",
  docs: {
    // theme: themes.dark,
    container: DocsContainer,
  },
};

export const decorators = [
  (Story) => (
    <div className={useDarkMode() ? darkTheme.className : "light"}>
      <Story />
    </div>
  ),
];

Also published in my gist.

@martijnhalekor
Copy link

martijnhalekor commented Apr 5, 2022

Same problem here, docs are not updating when changing theme. Would love a similar option for styling docs, just like { stylePreview: true }

For now I'm sticking with the hack by @hugoattal because I'm also using Vue for my UI library. I tried the custom DocsContainer solution, but I can't install React as a devDependency in Storybook 6.4.20, because npm is complaining about dependency conflicts... Let's hope this Storybook issue gets solved.

I'm not using React (but Vue3) and didn't see anything on creating containers in Vue (I'm not even sure it's possible).

So I went with a very simple (but not reactive) solution, adding this in my preview.ts:

export const parameters = {
    /* ... */
    docs: {
        get theme() {
            let isDarkMode = parent.document.body.classList.contains("dark");
            return isDarkMode ? themes.dark : themes.light;
        }
    },
    /* ... */
};

@keemor
Copy link

keemor commented Jun 28, 2022

Here is how I used @fedek6 DocsContainer with MUI5 theme:

import { createTheme, CssBaseline, ThemeProvider } from "@mui/material";
import { getDesignTokens } from "theme/theme";
import { useDarkMode } from "storybook-dark-mode";
import { themes } from "@storybook/theming";
import { DocsContainer } from "./DocsContainer";

export const parameters = {
  actions: { argTypesRegex: "^on[A-Z].*" },
  controls: {
    matchers: {
      color: /(background|color)$/i,
      date: /Date$/,
    },
  },
  darkMode: {
    dark: { ...themes.dark },
    light: { ...themes.normal },
  },
  docs: {
    container: DocsContainer,
  },
};

function ThemeWrapper(props) {
  const mode = useDarkMode() ? "dark" : "light";
  const theme = createTheme(getDesignTokens(mode));
  return (
    <ThemeProvider theme={theme}>
      <CssBaseline /> {props.children}
    </ThemeProvider>
  );
}

export const decorators = [
  (Story) => (
    <ThemeWrapper>
      <Story />
    </ThemeWrapper>
  ),
];

@dartess
Copy link
Contributor

dartess commented Aug 15, 2022

Hey!

It's time to smoothly change the name to "Storybook 7 docs theming"

In storybook@7 (alpha now) BaseContainer has prop theme, and passing theme is now much easier.

But storybook-dark-mode does not set the class for the body in the new docs page. You can do it yourself. But I don't know how to get the global parameters of the storybook correctly (the way I found does not converge on types and I use ts-ignore).

The result of my research is this:

diff --git a/.storybook/components/DocContainer.tsx b/.storybook/components/DocContainer.tsx
index 2e0d9fb8b..e1be68bf2 100644
--- a/.storybook/components/DocContainer.tsx
+++ b/.storybook/components/DocContainer.tsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import React, { useEffect } from 'react';
 import { DocsContainer as BaseContainer } from '@storybook/addon-docs';
 import { useDarkMode } from 'storybook-dark-mode';
 
@@ -15,24 +15,16 @@ so a workaround is used.
 export const DocsContainer: typeof BaseContainer = ({ children, context }) => {
   const dark = useDarkMode();
 
+  useEffect(() => {
+    // @ts-ignore
+    const { darkClass, lightClass } = context.store.projectAnnotations.parameters.darkMode;
+    const [addClass, removeClass] = dark ? [darkClass, lightClass] : [lightClass, darkClass]
+    document.body.classList.remove(removeClass);
+    document.body.classList.add(addClass);
+  }, [dark])
+
   return (
-    <BaseContainer
-      context={{
-        ...context,
-        storyById: id => {
-          const storyContext = context.storyById(id);
-          return {
-            ...storyContext,
-            parameters: {
-              ...storyContext?.parameters,
-              docs: {
-                theme: dark ? themes.dark : themes.light,
-              },
-            },
-          };
-        },
-      }}
-    >
+    <BaseContainer context={context} theme={dark ? themes.dark : themes.light}>
       {children}
     </BaseContainer>
   );

Tested on version 7.0.0-alpha.19 (everything may change by release)

@hipstersmoothie
Copy link
Owner

I'm not really sure what the solution is here but if there are any that could be landed in the package feel free to make a PR!

@hipstersmoothie hipstersmoothie added the help wanted Extra attention is needed label Dec 5, 2022
@sneko
Copy link

sneko commented Jan 2, 2023

After upgrading to SB7+Next+Webpack my addons channel is no longer working (so no useDarkMode() possible) and didn't find for now the origin (ref: #205).

So for me, the quick solution is to use as wrapper:

import { DocsContainer as BaseContainer } from '@storybook/addon-docs';
import { themes } from '@storybook/theming';
import React, { useEffect, useState } from 'react';

function isDarkInStorage(): boolean {
  const themeString = localStorage.getItem('sb-addon-themes-3');

  if (themeString) {
    const theme = JSON.parse(themeString);

    return theme['current'] !== 'light';
  }

  return false;
}

export const ThemedDocsContainer = ({ children, context }) => {
  const [isDark, setIsDark] = useState(isDarkInStorage());

  const handler = () => {
    setIsDark(isDarkInStorage());
  };

  useEffect(() => {
    window.addEventListener('storage', handler);

    return function cleanup() {
      window.removeEventListener('storage', handler);
    };
  });

  return (
    <BaseContainer context={context} theme={isDark ? themes.dark : themes.light}>
      {children}
    </BaseContainer>
  );
};

(big sorry for this dirty workaround)

@GaroGabriel
Copy link

I was able to get both the args table to work correctly with subcomponents and the controls section to show up in dark mode with this:

    <BaseContainer
      context={{
        ...context,
        storyById: (id) => {
          const storyContext = context.storyById(id)
          return {
            ...storyContext,
            parameters: {
              ...storyContext?.parameters,
              docs: {
                ...storyContext?.parameters?.docs,
                theme: dark ? darkTheme : themes.light,
              },
            },
          }
        },
      }}
    >

thank you

@mel-miller
Copy link

  1. Create .storybook/DocsContainer.js
import React from "react";
import { DocsContainer as BaseContainer } from "@storybook/addon-docs/blocks";
import { useDarkMode } from "storybook-dark-mode";
import { themes } from "@storybook/theming";

export const DocsContainer = ({ children, context }) => {
  const dark = useDarkMode();

  return (
    <BaseContainer
      context={{
        ...context,
        storyById: (id) => {
          const storyContext = context.storyById(id);
          return {
            ...storyContext,
            parameters: {
              ...storyContext?.parameters,
              docs: {
                ...storyContext?.parameters?.docs,
                theme: dark ? themes.dark : themes.light,
              },
            },
          };
        },
      }}
    >
      {children}
    </BaseContainer>
  );
};

Thanks @fedek6 - This solution also worked for me, but now my source code block is only showing raw code — equivalent to setting the docs source parameter as type: 'code' . Do you know if it's possible to edit the custom DocsContainer to allow for type: 'dynamic'?

@soullivaneuh
Copy link

@dartess I did nearly the similar but without having to hack with the document.body object:

diff --git a/.storybook/components/DocContainer.tsx b/.storybook/components/DocContainer.tsx
index 84bf99b..abd2e6d 100644
--- a/.storybook/components/DocContainer.tsx
+++ b/.storybook/components/DocContainer.tsx
@@ -13,27 +13,13 @@ import {
 } from '@storybook/theming';
 
 // @see https://github.com/hipstersmoothie/storybook-dark-mode/issues/127#issuecomment-1070524402
-export const DocsContainer: FC<DocsContainerProps> = ({ children, context }) => {
+export const DocsContainer: FC<DocsContainerProps> = ({ children, ...rest }) => {
   const dark = useDarkMode();
 
   return (
     <BaseContainer
-      context={{
-        ...context,
-        storyById: (id) => {
-          const storyContext = context.storyById(id);
-          return {
-            ...storyContext,
-            parameters: {
-              ...storyContext?.parameters,
-              docs: {
-                ...storyContext?.parameters?.docs,
-                theme: dark ? themes.dark : themes.light,
-              },
-            },
-          };
-        },
-      }}
+      {...rest}
+      theme={dark ? themes.dark : themes.light}
     >
       {children}
     </BaseContainer>

The only thing I have to do is to fill the theme prop with the right one.

Why do you need to play with the DOM body here? 🤔

@dartess
Copy link
Contributor

dartess commented Apr 7, 2023

@soullivaneuh it was necessary for storybook-dark-mode@2

Now I have the same version as you.

@zhimng
Copy link

zhimng commented May 12, 2023

Hey!

It's time to smoothly change the name to "Storybook 7 docs theming"

In storybook@7 (alpha now) BaseContainer has prop theme, and passing theme is now much easier.

But storybook-dark-mode does not set the class for the body in the new docs page. You can do it yourself. But I don't know how to get the global parameters of the storybook correctly (the way I found does not converge on types and I use ts-ignore).

The result of my research is this:

diff --git a/.storybook/components/DocContainer.tsx b/.storybook/components/DocContainer.tsx
index 2e0d9fb8b..e1be68bf2 100644
--- a/.storybook/components/DocContainer.tsx
+++ b/.storybook/components/DocContainer.tsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import React, { useEffect } from 'react';
 import { DocsContainer as BaseContainer } from '@storybook/addon-docs';
 import { useDarkMode } from 'storybook-dark-mode';
 
@@ -15,24 +15,16 @@ so a workaround is used.
 export const DocsContainer: typeof BaseContainer = ({ children, context }) => {
   const dark = useDarkMode();
 
+  useEffect(() => {
+    // @ts-ignore
+    const { darkClass, lightClass } = context.store.projectAnnotations.parameters.darkMode;
+    const [addClass, removeClass] = dark ? [darkClass, lightClass] : [lightClass, darkClass]
+    document.body.classList.remove(removeClass);
+    document.body.classList.add(addClass);
+  }, [dark])
+
   return (
-    <BaseContainer
-      context={{
-        ...context,
-        storyById: id => {
-          const storyContext = context.storyById(id);
-          return {
-            ...storyContext,
-            parameters: {
-              ...storyContext?.parameters,
-              docs: {
-                theme: dark ? themes.dark : themes.light,
-              },
-            },
-          };
-        },
-      }}
-    >
+    <BaseContainer context={context} theme={dark ? themes.dark : themes.light}>
       {children}
     </BaseContainer>
   );

Tested on version 7.0.0-alpha.19 (everything may change by release)

This is useful for me. Thanks

@lcallanan-instabase
Copy link

@soullivaneuh's solution works well except for a few style regressions. Swapping out theme (esp. light -> dark) changes the css class order which mangles styles:

Before theme swap After theme swap (link position changed & markdown heading is indented)
Screenshot 2023-05-18 at 10 25 38 AM Screenshot 2023-05-18 at 10 25 50 AM

Has anyone found a workaround that doesn't require reloading the docs iframe?

@dondevi
Copy link

dondevi commented Jun 3, 2023

@soullivaneuh's solution works well except for a few style regressions. Swapping out theme (esp. light -> dark) changes the css class order which mangles styles:

Before theme swap After theme swap (link position changed & markdown heading is indented)
Screenshot 2023-05-18 at 10 25 38 AM Screenshot 2023-05-18 at 10 25 50 AM
Has anyone found a workaround that doesn't require reloading the docs iframe?

😂 Still dirty:

<!-- preview-head.html -->
<style>
  /* Fix dynamic dark mode */
  #storybook-docs h1>a:first-child,
  #storybook-docs h2>a:first-child,
  #storybook-docs h3>a:first-child,
  #storybook-docs h4>a:first-child,
  #storybook-docs h5>a:first-child,
  #storybook-docs h6>a:first-child {
    float: left;
    line-height: inherit;
    padding-right: 10px;
    margin-left: -24px;
    color: inherit;
  }
</style>

@WilliamABradley
Copy link

WilliamABradley commented Mar 2, 2024

Finally got this working for me on react-vite 😅

Not sure if it is a vite specific issue, react 18 issue, or something, but overriding the context property seems to cause an error relating to useEffect being null weirdly.

This was my least painful complete solution for theme to be controlled by the global parameters:

import React from "react";
import type { Preview } from "@storybook/react";
import { DocsContainer, DocsContainerProps } from "@storybook/blocks";
import { themes } from "@storybook/theming";

const preview: Preview = {
  globalTypes: {
    theme: {
      description: "Global theme for components",
      defaultValue: "Dark",
      toolbar: {
        // The label to show for this toolbar item
        title: "Theme",
        icon: "circlehollow",
        // Array of plain string values or MenuItem shape (see below)
        items: ["Light", "Dark"],
        // Change title based on selected value
        dynamicTitle: true,
      },
    },
  },
  parameters: {
    actions: { argTypesRegex: "^on[A-Z].*" },
    controls: {
      matchers: {
        color: /(background|color)$/i,
        date: /Date$/,
      },
    },
    docs: {
      container: (props: DocsContainerProps) => {
        const { globals } = (props.context as any).store.globals;
        return (
          <DocsContainer
            {...props}
            context={props.context}
            theme={
              // Complains about missing properties, but it works
              (globals.theme === "Dark" ? themes.dark : themes.light) as any
            }
          />
        );
      },
    },
  },
};

export default preview;

@k-utsumi
Copy link

My project uses Storybook@7.6.17 with react-vite.
This worked fine for switching to dark mode.

preview.tsx:

import { DocsContainer, type DocsContainerProps } from '@storybook/blocks'
import type { Preview } from '@storybook/react'
import { themes } from '@storybook/theming'
import React, { type FC } from 'react'
import { useDarkMode } from 'storybook-dark-mode'

const { dark, light } = themes
const container: FC<DocsContainerProps> = ({ ...rest }) => (
  <DocsContainer {...rest} theme={useDarkMode() ? dark : light} />
)
export const parameters = {
  darkMode: { stylePreview: true },
  docs: { container },
}
const preview: Preview = { parameters }
export default preview

@paul-vd
Copy link

paul-vd commented Jul 28, 2024

On storybook v8 I get Storybook preview hooks can only be called inside decorators and story functions. any ideas?

@taikongfeizhu
Copy link

taikongfeizhu commented Aug 13, 2024

My project uses Storybook@^7.6.7 with webpack, it worked fine!

doc-container.tsx:

import { DocsContainer as BaseContainer } from "@storybook/addon-docs";
import { useDarkMode } from "storybook-dark-mode";
import { themes } from "@storybook/theming";

export const DocsContainer = ({ children, context, ...rest }) => {
  const { dark, light } = themes

  return (
    <BaseContainer
      context={context}
      {...rest}
      theme={useDarkMode() ? dark : light}
    >
      {children}
    </BaseContainer>
  );
};

prevew.tsx:

const parameters: Preview['parameters'] = {
 ...
  docs: {
    container: ({children, context}) => {
      return (
        <DocsContainer
          context={context}
        >
          {children}
        </DocsContainer>
      )
    },
  },
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests