Storybook lets us prototype components easily with various parameters.
In this article, we’ll look at how to work with decorators with Storybook.
Decorators
A decorator is a way to wrap stories with extra rendering functionality.
Wrap Stories with Extra Markup
We can wrap stories with extra markup with decorators.
For example, we can write:
src/stories/Button.stories.js
import React from 'react';
import { Button } from './Button';
export default {
title: 'Example/Button',
component: Button,
argTypes: {
backgroundColor: { control: 'color' },
},
decorators: [(Story) => <div style={{ margin: '20px' }}><Story /></div>]
};
const Template = (args) => <Button {...args} />;
export const Primary = Template.bind({});
Primary.args = {
primary: true,
label: 'Button',
};
export const Secondary = Template.bind({});
Secondary.args = {
label: 'Button',
};
export const Large = Template.bind({});
Large.args = {
size: 'large',
label: 'Button',
};
export const Small = Template.bind({});
Small.args = {
size: 'small',
label: 'Button',
};
We have the decorators
property with an array of functions that renders components around our component.
Story
is the component that we’re rendering in our story.
Context for Mocking
We can wrap our component with a higher-order component globally.
For example, we can write:
.storybook/preview.js
import { ThemeProvider } from 'styled-components';
export const decorators = [
(Story) => (
<ThemeProvider theme="default">
<Story />
</ThemeProvider>
),
];
to wrap the ThemeProvider
HOC from styled-components around the components in our stories.
Story Decorators
We can add decorators that are available within a story.
To add it, we just add the decorators
property to our story object:
src/stories/Button.stories.js
import React from 'react';
import { Button } from './Button';
export default {
title: 'Example/Button',
component: Button,
argTypes: {
backgroundColor: { control: 'color' },
},
};
const Template = (args) => <Button {...args} />;
export const Primary = Template.bind({});
Primary.args = {
primary: true,
label: 'Button',
};
Primary.decorators = [(Story) => <div style={{ margin: '20px' }}><Story /></div>]
to assign the decorators array to the decorators
property of the Primary
story.
Component Decorators
We can set decorators on all stories of a component.
To do that, we put the decorators
property in the object that we export:
src/stories/Button.stories.js
import React from 'react';
import { Button } from './Button';
export default {
title: 'Example/Button',
component: Button,
argTypes: {
backgroundColor: { control: 'color' },
},
decorators: [(Story) => <div style={{ margin: '20px' }}><Story /></div>]
};
Global Decorators
We can add global decorators in the .storybook/preview.js
file by exporting it:
import React from 'react';
export const decorators = [(Story) => <div style={{ margin: '20px' }}><Story /></div>]
We export the decorators
array to apply it everywhere.
Decorator Inheritance
Decorators are applied in a specific order.
Global ones are applied in the order they’re defined first.
Then component decorators are applied in the order they’re defined.
And story decorators are applied in the order they’re defined.
Conclusion
Decorators let us add extra markup to our component and render them in Storybook.