How to Inline HTML Stories in Storybook 5 Docs

Written by Tyler Sticka on

Storybook (the UI component playground we’ve enjoyed using lately) organizes its component examples into stories. These stories are displayed one at a time by default, but the Docs add-on lets you display as many as you’d like in a single page alongside background information, usage details and more.

Docs have two methods for rendering stories:

  • Iframe stories render in (you guessed it) an iframe element. Media queries will work as expected and state will be sandboxed, but their height isn’t responsive, and they load rather sluggishly.
  • Inline stories render directly in the page you’re viewing, which means they load a lot faster and don’t require height to be set. But because Storybook is written in React, this feature only works if our story functions are also written in (or converted to) React.

If you use the HTML “framework” (as we have), you’re limited to iframe stories by default. But we can change that, and with fewer than ten lines of configuration! Here’s how.

Getting started

First, let’s install the handy html-to-react package:

npm i -D html-to-react

Next, we import and initialize some dependencies in our .storybook/preview.js:

import { addParameters } from '@storybook/html';
import { Parser } from 'html-to-react';

const htmlToReactParser = new Parser();

Finally, we use addParameters to tell the Docs add-on how to parse our story before inlining:

addParameters({
  docs: {
    prepareForInline: (storyFn) => htmlToReactParser.parse(storyFn()),
  },
});

That’s it! Let’s try it out.

Usage

We can now add an inline property to our stories:

<Story name="Button/Example" inline>
  {`<button>Hello world!</button>`}
</Story>

And our button is free of its iframe prison!

This works no matter how the markup string is generated, so template loaders, knobs and more are fair game.

It seems kind of silly to convert plain HTML to a React component, which eventually converts it back to HTML for display. But I’m glad it takes so little custom code to pull off!

Optional: Inline by default

If you find yourself setting inline on more stories than not, consider enabling Docs’ inlineStories parameter as well:

addParameters({
  docs: {
    inlineStories: true,
    // ...
  },
});

Now stories will render inline by default, without needing an inline property.

You can disable this for individual stories:

<Story name="Button/Example" inline={false}>
  {`<button>Hello world!</button>`}
</Story>

Or for an entire file:

<Meta
  title="Button"
  parameters={{ docs: { inlineStories: false } }}
/>
Tyler Sticka

Tyler Sticka is Cloud Four’s VP of Design, allowing him to think about design systems every day. When he isn’t directing his team, sketching on sticky notes or nitpicking CSS, he enjoys reading comics, making video games and listening to weird music. He tweets as @tylersticka.

Never miss an article!

Get Weekly Digests


Leave a Comment

Please be kind, courteous and constructive. You may use simple HTML or Markdown in your comments. All fields are required.


Let’s discuss your project! Email Us