Skip to content
This repository has been archived by the owner on Nov 5, 2020. It is now read-only.

Source exposes decorators #50

Closed
tbredin opened this issue Jul 19, 2018 · 4 comments
Closed

Source exposes decorators #50

tbredin opened this issue Jul 19, 2018 · 4 comments
Labels

Comments

@tbredin
Copy link

tbredin commented Jul 19, 2018

Describe the bug
I've got a Card component that expands to fill its parent but doesn't make sense to present without a grid Container decorator. However I probably don't want to expose this grid Container decorator as the source, which seems to be how this is working.

Is there a way around this currently? unsure if this is a bug or expected behaviour (in which case a feature request!)

To Reproduce

import { storiesOf } from '@storybook/vue'
import VueInfoAddon from 'storybook-addon-vue-info'

// the component we wish to showcase
import Card from './index.vue'

// import our wrapper component to be used in the decorator, which we want to hide
import Container from '../Container/index.vue'

storiesOf('Card', module)
  .addDecorator(() => ({
    // Decorated with Container component
    components: {
      Container
    },
    template: '<container><story/></container>'
  }))
  .addDecorator(VueInfoAddon)
  .add('Card', () => ({
    components: { Card },
    template: '<card uri="/" text="Card title"></card>'
  }))

Expected behavior
I had hoped the source would show:
<card uri="/" text="Card title text"></card>

Instead this is currently showing:
<container><story/></container>

Obviously we'd ideally like this to automagically get the expected source, but I am not really across how decorators work in storybook and am unsure if it's possible?

Alternative Proposal
As a fallback second-best idea: One way I can imagine this working is to change the above example to use withInfo, in which case, could the source option also accept a string?
eg:

storiesOf('Card', module)
  .addDecorator(() => ({
    // Decorated with Container component
    components: {
      Container
    },
    template: '<container><story/></container>'
  }))
  .add('Card', withInfo({
    source: '<card uri="/" text="Card title text"></card>'
  })(() => ({
    components: { Card },
    template: '<card uri="/" text="Card title text"></card>'
  })))

A little clunky though (not DRY). Keen to hear thoughts on this issue.

@pocka pocka added the bug label Jul 23, 2018
@pocka
Copy link
Owner

pocka commented Jul 27, 2018

@tbredin Thank you for reporting 😸

It seems difficult to fix because this addon uses story component that was wrapped with decorators (in your example, we get <container><story/></container>, not <card ...>). I think it's hard to obtain "real" story source from this addon.
But, of course, I'll look for the way to archive this :)

As a fallback second-best idea: One way I can imagine this working is to change the above example to use withInfo, in which case, could the source option also accept a string?

This idea will makes possible to show correct story source, but writing duplicated template is not a good API design...

Is there a way around this currently? unsure if this is a bug or expected behaviour (in which case a feature request!)

With storysource addon and setting source option to false, you might see expected source.

@rbpaul2
Copy link

rbpaul2 commented Mar 20, 2019

Try switching the order of the decorators:

storiesOf('Card', module)
  .addDecorator(VueInfoAddon)
  .addDecorator(() => ({
    // Decorated with Container component
    components: {
      Container
    },
    template: '<container><story/></container>'
  }))
  .add('Card', () => ({
    components: { Card },
    template: '<card uri="/" text="Card title"></card>'
  }))

I had a similar problem- I had a container decorator in a specific story and the withInfo decorator added in the global storybook config.js. After moving my container decorator to the global config and placing it after the withInfo decorator, I was able to see the actual source in the addon panel.

// storybook/config.js
import { withInfo, setDefaults } from 'storybook-addon-vue-info'
addDecorator(withInfo)
setDefaults({
    header: false
})

const padded = () => {
    return {
        template: '<div style="padding: 3rem; font-size: 1rem;"><story/></div>',
    }
}
addDecorator(padded)

Not positive if the ordering will still work when the decorators are added locally to a specific story.

@vschimpf
Copy link

vschimpf commented May 7, 2019

I had the same problem. The only way to fix it without duplicating the template code was changing the code in the file @storybook\vue\dist\client\preview\index.js in the prepare method when it asks if innerStory is defined:

    if (innerStory) {
      if (story.template && story.template.indexOf('<story/>') > -1) {
        // improved code for decorated stories
        const keys = Object.keys(innerStory.options.STORYBOOK_WRAPS.extendOptions);
        for (let i = 0; i < keys.length; i++) {
          if (keys[i] != 'template' && !keys[i].startsWith('_'))
            story[keys[i]] = Object.assign({}, story[keys[i]] || {}, innerStory.options.STORYBOOK_WRAPS.extendOptions[keys[i]]);
        }

        story.template = story.template.replace('<story/>', innerStory.options.STORYBOOK_WRAPS.extendOptions.template);
      } else {
        // original code
        story.components = Object.assign({}, story.components || {}, {
          story: innerStory
        });
      }
    }

Until now it works like a charm.
I hope you can include this fix in the next version since having decorators is very common and necessary.

pocka added a commit that referenced this issue Sep 7, 2019
@pocka
Copy link
Owner

pocka commented Sep 7, 2019

Fixed in #113 (only works with >= SB5)

@pocka pocka closed this as completed Sep 7, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

4 participants