storybook/docs/api/addons.md
2020-08-11 02:51:40 +01:00

9.0 KiB
Raw Blame History

title
Addons

Addons extend Storybook with features and integrations that are not built into the core. Most Storybook features are implemented as addons. For instance: documentation, accessibility testing, interactive controls, and design previews. The addon API makes it easy for you to configure and customize Storybook in new ways. There are countless addons made by the community that unlock time-saving workflows. What addons can do:

Browse the addon gallery to install an existing addon or as inspiration for your own addon. Read on to learn how to make an addon yourself.

Storybook basics

Before writing your first addon, lets take a look at the basics of Storybooks architecture. While Storybook presents a unified user interface, under the hood its divided down the middle into Manager and Preview.

The Manager is the UI where Storybooks search, navigation, toolbars, and addons are rendered. The Preview area is an iframe where stories are rendered.

Storybook detailed window

Because Manager and Preview run in separate iframes, they communicate across a communication channel. When you select a story within the Manager an event is sent across the channel and the selected story is rendered inside the Preview.

Many of the addon APIs youll read about below are abstractions to help make this communication transparent.

Getting started

Lets write a simple addon for Storybook which:

  • Adds a new “My Addon” panel
  • Retrieves a custom “myAddon” parameter from stories
  • Displays the parameter data in the panel

Add story parameters

Lets start by writing a story for our addon that exposes a custom parameter. The idea is that our addon will show this parameter in the addon panel.

<CodeSnippets paths={[ 'react/button-story-with-addon-example.js.mdx', ]} />

Because we added the story at the component level, the myAddon parameter is associated with all stories defined in the file.

Add a panel

Now lets add a panel to Storybook in a file called register.js, which is the entry point for addons to register themselves.

<CodeSnippets paths={[ 'common/storybook-addon-panel-initial.js.mdx', ]} />

This is boilerplate code for any addon that adds a panel to Storybook, and theres really not much going on here. In this case, were just adding a static div that renders when the panel is selected in Storybooks UI.

Display story parameter

Next, lets replace the MyPanel component from above to show the parameter.

<CodeSnippets paths={[ 'common/storybook-addon-change-panel.js.mdx', ]} />

The new version is made smarter by useParameter, which is a React hook that updates the parameter value and re-renders the panel every time the story changes.

The addon API provides hooks like this so all of that communication can happen behind the scenes. That means you can focus on your addon's functionality.

Register the addon

Finally, lets hook it all up. Addons are typically published as standalone packages, but they can also be written locally in an existing Storybook project. Well make our addon a local addon.

Update your .storybook/main.js:

<CodeSnippets paths={[ 'common/storybook-main-register-addon.js.mdx', ]} />

The path can be an absolute location on your file system, or a path relative to your .storybook directory (e.g. ./my-addon/register.js if you defined the addon inside your .storybook folder).

If you get an error similar to:

ModuleParseError: Module parse failed: Unexpected token (92:22)

You may need an appropriate loader to handle this file type.
       var value = this.state.value;
      var active = this.props.active;
      return active ? <div>{value}</div> : null;
     }
   }]);

It is likely because you do not have a .babelrc file or do not have it configured with the correct presets:

{
  "presets": ["@babel/preset-env", "@babel/preset-react"]
}

Now restart/rebuild Storybook and your addon should appear in the addons panel. Furthermore, as you navigate between stories, the parameter displayed should update accordingly.

Next steps

In the previous example, we introduced the structure of an addon, but barely scratched the surface of what addons can do.

To dive deeper we recommend Learn Storybooks “creating addons” tutorial. Its an excellent walkthrough that covers the same ground as the above introduction, but goes further and leads you through the full process of creating a realistic addon.

Addon recipes

Once you understand the basics of writing an addons, there are a variety of common enhancements to make your addon better.

Disabling the addon panel

Its possible to disable the addon panel for a particular story.

To make that possible, you need to pass the paramKey element when you register the panel:

<CodeSnippets paths={[ 'common/storybook-addon-disable-addon.js.mdx', ]} />

Then when adding a story, you can then pass a disabled parameter.

<CodeSnippets paths={[ 'react/button-story-disable-addon.js.mdx', ]} />

Styling your addon

Storybook uses Emotion for styling, AND we provide a theme which can be set by the user!

We recommend you also use Emotion to style your addons UI components. That allows you to use the active Storybook theme to deliver a seamless developer experience. If you dont want to use Emotion, you can use inline styles or another css-in-js lib. You can receive the theme as a prop by using the withTheme hoc from Emotion. Read more about theming.

Storybook components

Addon authors can develop their UIs using any React library. But we recommend using Storybooks own UI components in @storybook/components to build addons faster. When you use Storybook components you get:

  • Battled tested off-the-shelf components
  • Storybook native look and feel
  • Built-in support for Storybook theming

You can check them out in Storybooks own storybook

Packaging

In the example above, we showed how to write a local addon inside an existing Storybook project. To distribute your addon for others, package the addon into a standalone NPM module.

For a good template of an addon packaged as an NPM module, check out [@storybook/addon-controls].

It contains addon code similar to what weve written above. It also contains:

  • A package.json file that declares the module
  • Peer dependencies of react and @storybook/addons -A register.js file at the root level written as an ES5 modules
  • A src directory containing the ES6 addon code
  • A dist directory containing transpiled ES5 code on publish

Your packaged Storybook addon needs to be written in ES5. If you are using ES6, then you need to transpile it.

When you are developing your addon as a package, you cant use npm link to add it to your project. Instead add your package as a local dependency into your package.json:

{
  "dependencies": {
    "@storybook/addon-controls": "file:///home/username/myrepo"
  }
}

Addon presets

Storybook presets are collections of Storybook configurations that get applied automatically when you create a /preset.js entry point in your addon and then list that addon in your projects .storybook/main.js addons field.

Common uses for presets include:

  • Register an addons register.js.
  • Set global parameters for the addon (e.g. addon-backgrounds).
  • Add global decorators for the addon (e.g. addon-a11y).
  • Set up webpack customizations for the addon (e.g. addon-docs).

Heres an example of typical preset file:

<CodeSnippets paths={[ 'common/storybook-addon-preset-example.js.mdx', ]} />

For more information on presets, see the presets docs.

Writing presets

If you want to learn more how you can write your own presets, read the documentation

Addons API

If you want to expand your knowledge on the Addons API, read the documentation