Switch storybook background through global parameter
Asked Answered
P

1

6

I have the following globalTypes to enable a toolbar in storybook that lets me select the theme:

export const globalTypes = {
  theme: {
    name: 'Theme',
    description: 'Global theme',
    defaultValue: MyTheme.Light,
    toolbar: {
      icon: 'mirror',
      items: [MyTheme.Light, MyTheme.Dark],
      showName: true,
      dynamicTitle: true,
    },
  },
};

This works fine and I can switch the theme through the toolbar:

theme switcher

Now I want to set the background color of the story (background-color of the body) according to the theme, but I cannot figure out how to do that for all stories globally.

I know how to configure different background colors, but I have no idea how to switch them based on the theme set in context.globals. How does this work?

Putrescine answered 25/11, 2022 at 19:21 Comment(2)
Hi magnattic. Can you specify versions of your dependecies?Coleen
I am currently running storybook and it's in version 6.5.10, but could upgrade to latest if that helps.Putrescine
C
3

You can use decorators to set global view and se

Like here

import { useEffect } from "react";
import "./preview.css";

enum MyTheme {
  Light = "light",
  Dark = "dark",
  Tomato = "tomato"
}

export const globalTypes = {
  theme: {
    name: "Theme",
    description: "Global theme",
    defaultValue: MyTheme.Light,
    toolbar: {
      icon: "mirror",
      items: [
        {
          title: "light",
          value: MyTheme.Light
        },
        { title: "dark", value: MyTheme.Dark },
        { title: "tomato", value: MyTheme.Tomato }
      ],
      showName: true,
      dynamicTitle: true
    }
  }
};

const clearStyles = (element: HTMLElement) => {
  for (const className of Object.values(MyTheme)) {
    element.classList.remove(className);
  }
};

const applyStyle = (element: HTMLElement, className: string) => {
  element.classList.add(className);
};

const WithThemeProvider = (Story, context) => {
  useEffect(() => {
    const body = window.document.body;
    clearStyles(body);
    applyStyle(body, context.globals.theme);
    return () => {
      clearStyles(body);
    };
  }, [context.globals.theme]);

  return <Story />;
};
export const decorators = [WithThemeProvider];

I know it might feel "dirty" to work directly with body. But it is suggested way for instance addons decorator.

Coleen answered 28/11, 2022 at 15:12 Comment(3)
I am doing something similar right now, but this is not the same as switching the background color in storybook. The problem with this solution is that it only switches the content right around the component while background in storybook applies to the whole story.Putrescine
To clarify, setting the background via storybook backgrounds actually changes the body color which looks a lot different than adding a surrounding div. That's what I would like to achieve. It's even possible with a URL parameter, but I can't figure out how to do this programmatically based on globals.Putrescine
@Putrescine Updated. In short just update body as html element.Coleen

© 2022 - 2024 — McMap. All rights reserved.