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,
});
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,
});
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];
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',
};
- 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,
},
},
};
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>
)}
</>
);
};
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>
);
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 };
After that completing these steps you can find option dropdown at top of storybook toolbar.
Top comments (1)
"Great explanation! Customizing Storybook with themes and layouts seems super flexible. Thanks for sharing the detailed setup steps!"
Dan and Shay Wife Died