magnattic
magnattic

Reputation: 13018

Switch storybook background through global parameter

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?

Upvotes: 6

Views: 3714

Answers (1)

Talgat Saribayev
Talgat Saribayev

Reputation: 1938

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.

Upvotes: 3

Related Questions