storybook: `preview-body.html` not working as expected (?)

Hi, thanks for taking the time to look into this.

Describe the bug

The rendered content is not being appended in the preview-body.html file as the documentation suggests:

https://storybook.js.org/docs/configurations/add-custom-body/

To Reproduce

Add a preview-body.html file inside the .storybook config folder as suggested in the docs, containing a single custom <div id="custom-root"></div> div wrapper.

Expected behavior

I would expect this element to be the root of the rendered content, unless I’m missing something. Instead, the usual #root div container is used.

Screenshots

As shown in the screenshot, an extra div is added to the content, but this div is empty and is not serving the purpose of being the root for the rendered content.

Screenshot 2020-04-13 at 12 23 44

System:

Environment Info:

  System:
    OS: macOS Mojave 10.14.6
    CPU: (8) x64 Intel(R) Core(TM) i7-7700HQ CPU @ 2.80GHz
  Binaries:
    Node: 12.7.0 - ~/.nvm/versions/node/v12.7.0/bin/node
    Yarn: 1.21.1 - /usr/local/bin/yarn
    npm: 6.10.0 - ~/.nvm/versions/node/v12.7.0/bin/npm
  Browsers:
    Chrome: 80.0.3987.163
    Firefox: 74.0.1
    Safari: 13.1
  npmPackages:
    @storybook/react: ^5.0.6 => 5.2.8

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 13
  • Comments: 28 (15 by maintainers)

Commits related to this issue

Most upvoted comments

It’s extremely surprising that using the documented custom root file just injects that into the DOM and continues to use an unaltered div#root.

I expected that the custom root would be used instead, so that I can put the custom classes I need on that root.

I had no issue with the div#root itself, but I needed to wrap my Stories into a specific div with a class (eg. class="v-app"). I expected that the preview-body.html will help solving this, but as already mentioned by others, its not.

Workaround

The way @IuliiaBondarieva mentioned here would also work, I did this temporary for me:

// preview.js
document.body.onload = function() {
  document.body.classList.add("v-app");
};

Final Solution: Global decorators

Documentation Finally I found out that its probably the cleanest way to simply solve it with a “global decorator”:

// preview.js
export const decorators = [
  () => ({ template: '<div class="v-app"><story /></div>' }),
];

This solves my problem. It took me some time to understand this, so maybe it helps someone else too:

// generated storybook html
<div id="root">
  <div class="v-app">
    <button type="button">Button content</button>
  </div>
</div>

Maybe it would be good to make this more clear in the documentation?!

I discovered that inside your preview-body.html, if you use the id of storybook-root it will be used instead of the storybook-root generated by system.

Here is the contents of my preview-body.html

<ace-styles></ace-styles>
<div id="storybook-root" class="ace-con"></div>

Like this I can add my pre-requisite tag of ace-styles at the sibling level of story, and add my pre-requisite class of ace-con to story container.

It results in a structure of

<body>
<ace-styles></ace-styles>
<div id="storybook-root" class="ace-con">
  <!-- my stories are output here -->
</div>
  ...
<div id="storybook-root"></div>
<!-- system generated one stays empty lol -->

Recently started playing around with Daisy UI which requires data attribute on the html element unfortunately to set a theme and decorators just didn’t do enough.

Here’s what worked in the end. Thanks @IuliiaBondarieva

document.body.onload = function () {
  document.getElementsByTagName('html')[0].setAttribute('data-theme', 'light');
};

yeah, i can handle that

Needed it to add attribute on DOM Element. Found some workaround for now. Updated loadStories function in .storybook/config.js:


function loadStories() {
  document.body.onload = function () {
    document.body.setAttribute('theme', 'myTheme')
  }

  req.keys().forEach(filename => req(filename))
}

Have the same problem 😕