Storybook: addDecorator documentation for @storybook/html

Created on 14 Dec 2018  路  6Comments  路  Source: storybookjs/storybook

Hi,

First and foremost, thank you for Storybook, I love it! Used it across multiple React projects, and I am now experiencing with the @storybook/html package

Bug or support request summary

I am currently implementing Storybook in a project that does not contain React and if possible I would like to keep it that way. Thus me using @storybook/html.
I wanted to use the addDecorator function exposed in the package, however I was unable to make it work nor find documentation regarding its usage.

Steps to reproduce

Following the documentation from @storybook/react#addDecorator I attempted a few thing to add a global decorator

import { configure, addDecorator } from "@storybook/html";

// ...

addDecorator(story => {
  const wrapper = document.createElement("section");
  wrapper.appendChild(story); // also tried `story()`
  return wrapper;
});

// ...

The reason why I tried the above is that it is what seems to be the closest to what @storybook/react does

Please specify which version of Storybook and optionally any affected addons that you're running

  • @storybook/html

Affected platforms

All

Work summary

I'd like to get a bit of help from someone to explain how this feature works.

And after I am more than happy to open a PR to document that on the Storybook website

html inactive question / support

Most helpful comment

I have a similar case (where I want to wrap elements with Bootstrap classes) and I did the following:

const storyAsString = (story) => `<div class="container m-5">${story}</div>`;
const storyAsNode = (story) => {
  const wrapper = document.createElement('div');
  wrapper.className = 'container m-5';
  wrapper.appendChild(story);
  return wrapper;
};

addDecorator(story => {
  const tale = story();
  return typeof tale === "string" ? storyAsString(tale) : storyAsNode(tale);
});

All 6 comments

Hello @gsouquet, thank you for the kind words!

What does your storyFn return?

You should call it and depending on what you return from your storyFn do different things..

  • If your storyFn returns a string, you'll need to use innerHTML or a DomParser.
  • If your story returns a Element instance, you can set as child.

Storybook internally should be able to do both.

My story looks like the following

storiesOf("VideoContext", module)
    .add("Code playground", () => {

        const canvas = document.createElement("canvas");

        // Do canvas operation

        return canvas;
    });

And my decorator is meant to be a global decorator

import { configure, addDecorator } from '@storybook/html';

addDecorator(storyFn => {
  const wrapper = document.createElement("section");
  wrapper.appendChild(storyFn());
  return wrapper;
});

function loadStories() {
    require('../stories/index.js');
}

configure(loadStories, module);

I added the addDecorator there following the documentation on https://storybook.js.org/basics/writing-stories/

After inspecting the DOM it looks like my decorator is not taken in account at all.

screen shot 2018-12-14 at 11 42 36

Any ideas on what I am doing wrong?
Looking at your response above it seems that I a return an Element instance and set my storyFn as a child using the DOM API

Hi everyone! Seems like there hasn't been much going on in this issue lately. If there are still questions, comments, or bugs, please feel free to continue the discussion. Unfortunately, we don't have time to get to every issue. We are always open to contributions so please send us a pull request if you would like to help. Inactive issues will be closed after 30 days. Thanks!

Hey there, it's me again! I am going close this issue to help our maintainers focus on the current development roadmap instead. If the issue mentioned is still a concern, please open a new ticket and mention this old one. Cheers and thanks for using Storybook!

Hey @gsouquet, if storyFn() returns an HTML string, which are allowed as stories, you can do the following:

addDecorator(story => `<section>${storyFn()}</section>`);

I have a similar case (where I want to wrap elements with Bootstrap classes) and I did the following:

const storyAsString = (story) => `<div class="container m-5">${story}</div>`;
const storyAsNode = (story) => {
  const wrapper = document.createElement('div');
  wrapper.className = 'container m-5';
  wrapper.appendChild(story);
  return wrapper;
};

addDecorator(story => {
  const tale = story();
  return typeof tale === "string" ? storyAsString(tale) : storyAsNode(tale);
});
Was this page helpful?
0 / 5 - 0 ratings

Related issues

zvictor picture zvictor  路  3Comments

oriSomething picture oriSomething  路  3Comments

tlrobinson picture tlrobinson  路  3Comments

arunoda picture arunoda  路  3Comments

ZigGreen picture ZigGreen  路  3Comments