How to customize storybook (custom theme and layout option)?
Vishesh Tiwari

Vishesh Tiwari @vishesh-tiwari

About: Vishesh Tiwari is a dedicated IT professional with over 5+ years of experience. Specializing in the Java Spring Boot and React JS tech stack, Vishesh excels as a Full Stack Java Developer.

Location:
India
Joined:
Oct 28, 2024

How to customize storybook (custom theme and layout option)?

Publish Date: Dec 6 '24
2 1

Hi devs,

In this article , I am going to discuss about how can we customize our storybook which includes -

  • Custom theme ( dark or light )
  • Custom layout ## How to setup custom background colour with theme ? I am assuming you have done basic setup of storybook. If you have then in your project structure file named preview.tsx or preview.ts will be present where we will all customization code , if this file not present then you can create it. And second file you need create name as CustomTheme.ts which having content as below

import { create } from '@storybook/theming';
import logo from './my-app-logo.svg';
export default create({
  base: 'light',
  brandTitle: 'My app name',
  brandUrl: 'https://myapp.com',
  brandImage: logo,
  appContentBg: 'white',
  appBorderColor: 'grey',
  appBorderRadius: 4,
});

Enter fullscreen mode Exit fullscreen mode

After that create one file named as manager.ts if it is not present on your .storybook work directory and this

import { addons } from '@storybook/addons';

import CustomTheme from './CustomTheme';

addons.setConfig({
  theme: CustomTheme,
});

Enter fullscreen mode Exit fullscreen mode

Now lets move to preview.tsx file , we will start defining some configuration as below with withThemeProvider variable.


const Theme = {
  LIGHT: 'light',
  DARK: 'dark',
};

const customBackgrounds = {
  values: [
    {
      name: Theme.LIGHT,
      value: 'white',
    },
    {
      name: Theme.DARK,
      value: '#333333',
    },
  ],
};

const parameters = {
  backgrounds: customBackgrounds,
  viewport: {
  },
};


const getThemeColor = (theme: string) => {
  const { value } = parameters.backgrounds.values.find(({ name }) => name === theme);
  return value;
};

const withThemeProvider = (Story, storyContext) => {
  const { globals } = storyContext;
  const currentLayout: string = globals.layout;
  const currentFont: BackyardFonts = globals.font;
  const currentBackGround = globals.backgrounds?.value ?? 'white';
  const currentTheme: any = currentBackGround === 'white' ? Theme.LIGHT : Theme.DARK;
  const currentBackground: string = getThemeColor(currentTheme);

  useEffect(() => {
    document.body.setAttribute('backgroundColor', currentBackground);
  }, [currentBackground, currentFont]);

  return (
    <ThemeProvider
      theme={currentTheme}
      font={currentFont}
    >
      <GlobalStyles />
      <Story />
    </ThemeProvider>
  );
};

const decorators = [withThemeProvider];
Enter fullscreen mode Exit fullscreen mode

After adding these configuration you can change background colour with storybook theme.

How to setup custom layout ?

For setting up storybook with custom layout you need to following setup given below -

  • Defining custom layout which is going to appear as option in storybook

const Layout = {
  DEFAULT: 'default',
  WITH_L1: 'Layout 1',
  WITH_L2: 'Layout 2',
};
Enter fullscreen mode Exit fullscreen mode
  • Now we need add layout as option using global parameter

const globalTypes = {
  layout: {
    description: 'Layouts',
    defaultValue: Layout.DEFAULT,
    toolbar: {
      title: 'Layout',
      items: [
        { value: Layout.DEFAULT, title: 'Default' },
        { value: Layout.WITH_L1, title: 'Layout 1' },
        { value: Layout.WITH_L2, title: 'Layout 2' },
      ],
      dynamicTitle: true,
    },
  },
};

Enter fullscreen mode Exit fullscreen mode

Now we to do some slight changes in withThemeProvider

const withThemeProvider = (Story, storyContext) => {
  const { globals } = storyContext;
  const currentLayout: string = globals.layout;
  const currentBackground: string = getThemeColor(currentTheme);

  return (
    <>
      {currentLayout === Layout.DEFAULT && <Story />}
      {currentLayout === Layout.WITH_L1 && (
        <L1>
          <Story />
        </L1>
      )}
      {currentLayout === Layout.WITH_SIDEBAR && (
        <L2>
          <Story />
        </L2>
      )}
    </>
  );
};

Enter fullscreen mode Exit fullscreen mode

You can define layouts as component anywhere and export it in preview.tsx file -

const L1 = ({ children }) => (
  <StyledRootWrapper>
    <StyledNavContainer />
    <StyledChildren>{children}</StyledChildren>
  </StyledRootWrapper>
);

const L2 = ({ children }) => (
  <StyledRootWrapper>
    <StyledNavContainer />
    <StyledChildren>{children}</StyledChildren>
  </StyledRootWrapper>
);
Enter fullscreen mode Exit fullscreen mode

Whole code snippet look like for preview.tsx -

import { ThemeProvider } from '@backyard/react';
import { GlobalStyles } from './Container';
import { L1, L2 } from './customLayout';
import { useEffect } from 'react';
import {
  customBackgrounds,
  Layout,
  Theme,
} from './configurations';
import React from 'react';

const parameters = {
  backgrounds: customBackgrounds,
};

const getThemeColor = (theme: string) => {
  const { value } = parameters.backgrounds.values.find(({ name }) => name === theme);
  return value;
};

const withThemeProvider = (Story, storyContext) => {
  const { globals } = storyContext;
  const currentLayout: string = globals.layout;
  const currentBackGround = globals.backgrounds?.value ?? 'white';
  const currentTheme: any = currentBackGround === 'white' ? Theme.LIGHT : Theme.DARK;
  const currentBackground: string = getThemeColor(currentTheme);

  useEffect(() => {
    document.body.setAttribute('backgroundColor', currentBackground);
  }, [currentBackground, currentFont]);

  return (
      <ThemeProvider
      theme={currentTheme}>
      {currentLayout === Layout.DEFAULT && <Story />}
      {currentLayout === Layout.WITH_L1 && (
        <L1>
          <Story />
        </L1>
      )}
      {currentLayout === Layout.WITH_SIDEBAR && (
        <L2>
          <Story />
        </L2>
      )}
    </ThemeProvider>
  );
};

const globalTypes = {
  layout: {
    description: 'Layouts',
    defaultValue: Layout.DEFAULT,
    toolbar: {
      title: 'Layout',
      items: [
        { value: Layout.DEFAULT, title: 'Default' },
        { value: Layout.WITH_L1, title: 'Layout 1' },
        { value: Layout.WITH_L2, title: 'Layout 2' },
      ],
      dynamicTitle: true,
    },
  },
};


const decorators = [ withThemeProvider];

export { decorators, globalTypes, parameters };
Enter fullscreen mode Exit fullscreen mode

After that completing these steps you can find option dropdown at top of storybook toolbar.

Buy Me A Coffee

Comments 1 total

  • Cherry wills
    Cherry willsDec 12, 2024

    "Great explanation! Customizing Storybook with themes and layouts seems super flexible. Thanks for sharing the detailed setup steps!"

    Dan and Shay Wife Died

Add comment