Docs addon eval breaking Storybook Composition for certain prop default values
See original GitHub issueI’ve discovered an issue with the Docs addon while attempting to set up my team’s Storybook for Storybook Composition. This issue is always at play, it just doesn’t become immediately apparent until you try to compose the Storybook.
React Docgen produces default values as strings, so @shilman added an eval
to extractArgTypes
in https://github.com/storybookjs/storybook/pull/10812. This works well most of the time, however it produces undesirable behavior when the default value is a string that matches something that exists on the window
object.
In my case, I was trying to compose a Storybook with a Tooltip
component that has a placement
prop with the default 'top'
. Since window.top
provides a reference to the topmost window in the window hierarchy, this makes the Docs addon set the arg default to window
. Try it yourself - run eval('top')
in the console. Within that Storybook I haven’t noticed any issues, however when you try to compose it in another Storybook, you get an error when the composing storybook tries to serialize the window object from another origin: Uncaught DOMException: Blocked a frame with origin from accessing a cross-origin frame.
. You can see more info about my exploration of this issue in this comment. I opened a new issue because the one I linked originally relates to the actions addon (whereas this is an issue with docs).
Unfortunately, disabling the Docs addon for a specific story or set of stories is not an option, as the arg types seem to be extracted for every story regardless of this. The only way I can get Storybook Composition to work is by disabling the Docs addon entirely or by changing the default value of our component’s placement
prop (a breaking change that we would like to avoid).
If I wrap the try/catch in a conditional, everything works as expected:
let defaultValue = defaultSummary && (defaultSummary.detail || defaultSummary.summary);
if (!(defaultValue in window)) {
try {
defaultValue = eval(defaultValue);
} catch (_unused) {}
}
This is completely blocking us from using Composition. I’d be willing to submit a PR with some guidance, however I’m not sure if the above snippet is the best approach. Alternatively, we could use JSON.parse
instead of eval
, but it depends what other inputs you expect (there are no tests to reference that I can find). Would love some feedback! Thanks 🙂
To Reproduce Steps to reproduce the behavior:
- Set up a storybook with
@storybook/addon-docs
enabled - Add a story for a component with a prop that has a default value of a string that exists on the window object (e.g.
'top'
,'confirm'
, etc.) - Compose that storybook in another storybook
- Inspecting the arg types generated for the story, you will see that the default for that prop is
window
. - Get the
Uncaught DOMException: Blocked a frame with origin "http://localhost:9009" from accessing a cross-origin frame.
error when loading that story in a composing Storybook.
Expected behavior The default for the arg should be interpreted as expected (a string). Serializing stories across origins (for composition) should work as intended.
Issue Analytics
- State:
- Created 3 years ago
- Reactions:3
- Comments:9 (5 by maintainers)
Top GitHub Comments
Should be fixed in 6.3 by #14579
@anicholls I think there’s already an issue for this, so please look for it or open a new one and I can de-dupe. Thanks!!