Storybook for React — Decorators
Tags: react, webdev, programming, javascript
Published: 2021-01-24 21:41:45

**Check out my books on Amazon at https://www.amazon.com/John-Au-Yeung/e/B08FT5NT62**

**Subscribe to my email list now at http://jauyeung.net/subscribe/**


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.