Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[addon-controls] Story canvas isn't updated on Controls prop change for Vue component #11051

Closed
kvas-damian opened this issue Jun 5, 2020 · 25 comments

Comments

@kvas-damian
Copy link

Describe the bug
@[email protected] with docs and controls addons.
Story canvas isn't updated when I change prop value in Controls tab. Story uses correct prop value after manually re-rendering Canvas tab (change story in left menu or change tab to Docs and back).

To Reproduce
In vue-kitchen-sink:

  1. Install @storybook/[email protected]
  2. Run yarn storybook
  3. Go to Button > Rounded
  4. Change rounded prop in Controls tabs

No effect.

  1. Change tab to Docs and back to Canvas
    Component is rendered with selected prop values

Expected behavior
Component should be updated immediately

Screenshots
not-rerendered

Code snippets

import MyButton from '../Button.vue';

export default {
  title: 'Button',
  component: MyButton,
};

export const Rounded = (args) => ({
  components: { MyButton },
  template: '<my-button :color="color" :rounded="rounded">A Button with rounded edges</my-button>',
  data() {
    return args;
  },
});
Rounded.argTypes = {
  rounded: { defaultValue: true },
  color: { control: { type: 'color' }, defaultValue: '#f00' },
};

The same happens for MDX <Story> component:

<Story name='args'
    args={{rounded: false}}
>
    {(args) => {
        console.log(args);
        // works on args change
        return {
            components: { MyButton },
            data() {
                console.log('data', args);
                // works only on component render
                return args;
            },
            template: '<my-button :rounded="rounded">A Button with rounded edges</my-button>',
        };
    }}
</Story>

System:

Environment Info:

  System:
    OS: Linux 5.4 Ubuntu 20.04 LTS (Focal Fossa)
    CPU: (12) x64 Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz
  Binaries:
    Node: 13.13.0 - ~/.nvm/versions/node/v13.13.0/bin/node
    Yarn: 1.22.4 - ~/.nvm/versions/node/v13.13.0/bin/yarn
    npm: 6.14.4 - ~/.nvm/versions/node/v13.13.0/bin/npm
  Browsers:
    Chrome: 83.0.4103.61
    Firefox: 76.0.1
  npmPackages:
    @storybook/addon-a11y: 6.0.0-beta.21 => 6.0.0-beta.21 
    @storybook/addon-actions: 6.0.0-beta.21 => 6.0.0-beta.21 
    @storybook/addon-backgrounds: 6.0.0-beta.21 => 6.0.0-beta.21 
    @storybook/addon-controls: 6.0.0-beta.21 => 6.0.0-beta.21 
    @storybook/addon-docs: 6.0.0-beta.21 => 6.0.0-beta.21 
    @storybook/addon-knobs: 6.0.0-beta.21 => 6.0.0-beta.21 
    @storybook/addon-links: 6.0.0-beta.21 => 6.0.0-beta.21 
    @storybook/addon-storyshots: 6.0.0-beta.21 => 6.0.0-beta.21 
    @storybook/addon-storysource: 6.0.0-beta.21 => 6.0.0-beta.21 
    @storybook/addon-viewport: 6.0.0-beta.21 => 6.0.0-beta.21 
    @storybook/addons: 6.0.0-beta.21 => 6.0.0-beta.21 
    @storybook/source-loader: 6.0.0-beta.21 => 6.0.0-beta.21 
    @storybook/vue: 6.0.0-beta.21 => 6.0.0-beta.21 
@kvas-damian kvas-damian changed the title Story canvas isn't updated on Controls prop change for Vue component [addon-controls] Story canvas isn't updated on Controls prop change for Vue component Jun 5, 2020
@matheo
Copy link
Member

matheo commented Jun 5, 2020

@kvas-damian I'm not sure if the argTypes.defaultValue has the desired effect here,
I think you need to setup your default values following the docs:

Rounded.args = {
  rounded: true,
  color: '#f00',
};

your MDX seems to do that, but with rounded: false :-?

@Martskin
Copy link

Martskin commented Jun 5, 2020

I'm experiencing the same issue trying to get addon-controls working in Vue.

import MyButton from './MyButton';

export default {
  title: 'Button',
  component: MyButton,
  argTypes: {
    color: { control: { type: 'color' } }
  }
};

export const WithControls = (args) => ({
  components: { MyButton },
  template: '<my-button :color="color" :rounded="rounded">Hello Button</my-button>',
  data() {
    return args;
  },
});

https://github.com/Martskin/storybook-vue-playground/blob/master/stories/1-Button.stories.js

https://storybook-vue-playground.netlify.app/

@shilman shilman self-assigned this Jun 6, 2020
@shilman shilman mentioned this issue Jun 8, 2020
2 tasks
@shilman
Copy link
Member

shilman commented Jun 8, 2020

Great Caesar's ghost!! I just released https://github.com/storybookjs/storybook/releases/tag/v6.0.0-beta.23 containing PR #11076 that references this issue. Upgrade today to try it out!

You can find this prerelease on the @next NPM tag.

Closing this issue. Please re-open if you think there's still more to do.

@shilman shilman closed this as completed Jun 8, 2020
@Martskin
Copy link

Martskin commented Jun 8, 2020

Thanks! Release https://github.com/storybookjs/storybook/releases/tag/v6.0.0-beta.23 fixed it for me.

@shilman shilman reopened this Jun 9, 2020
@shilman
Copy link
Member

shilman commented Jun 9, 2020

I think I need to redo this per #11076 (comment), re-opening

@shilman
Copy link
Member

shilman commented Jun 10, 2020

I took a different approach this time, based on the knobs examples. Feedback welcome on the PR: #11115

@shilman
Copy link
Member

shilman commented Jun 11, 2020

Ooh-la-la!! I just released https://github.com/storybookjs/storybook/releases/tag/v6.0.0-beta.24 containing PR #11115 that references this issue. Upgrade today to try it out!

You can find this prerelease on the @next NPM tag.

Closing this issue. Please re-open if you think there's still more to do.

@shilman shilman closed this as completed Jun 11, 2020
@shilman
Copy link
Member

shilman commented Jun 11, 2020

Docs page controls broken, re-opening. Ugh. Cc @backbone87

@shilman
Copy link
Member

shilman commented Jun 12, 2020

Good golly!! I just released https://github.com/storybookjs/storybook/releases/tag/v6.0.0-beta.26 containing PR #11138 that references this issue. Upgrade today to try it out!

You can find this prerelease on the @next NPM tag.

Closing this issue. Please re-open if you think there's still more to do.

@shilman shilman closed this as completed Jun 12, 2020
@shilman
Copy link
Member

shilman commented Jun 12, 2020

Here's the most recent version of the Vue story based on the previous set of changes. Please check it out if you're tracking this issue:

https://github.com/storybookjs/storybook/blob/next/examples/vue-kitchen-sink/src/stories/components/button.stories.js#L1-L28

@kvas-damian
Copy link
Author

@shilman I think we still have this problem when we create MDX stories:

Add

<Story name='args'
    args={{rounded: false}}
>
    {(args) => {
        console.log(args);
        // works on args change
        return {
            components: { MyButton },
            data() {
                console.log('data', args);
                // works only on component render
                return args;
            },
            template: '<my-button :rounded="rounded">A Button with rounded edges</my-button>',
        };
    }}
</Story>

in https://github.com/storybookjs/storybook/blob/next/examples/vue-kitchen-sink/src/stories/addon-docs.stories.mdx to verify that. For me canvas isn't updated.

@shilman
Copy link
Member

shilman commented Jun 17, 2020

@shilman shilman reopened this Jun 17, 2020
@shilman shilman closed this as completed Jun 17, 2020
@kvas-damian
Copy link
Author

Ok, I see the problem. I have to pass args via props, not data. Thanks for help

@subhaze
Copy link

subhaze commented Sep 1, 2020

@shilman I'm running into Canvas not updating as well on info @storybook/vue v6.0.21

I may be doing this in a non-supported way, but, the way I'm structuring stories is via example.stories.mdx and building out .vue single file components, then importing them into the example.stories.mdx file.

This appears to work fine on the docs side, I can update a control and it will update the component in the docs, however, when moving over to Canvas, the updates from the docs side are there but doing any updates in the Control panel on Canvas wont update the component, but, if I switch over to docs with the updates, the component on the docs side has the updates from Canvas side, and if I switch immediately back to Canvas after that, the updates are there.

Basically I'm just trying to avoid doing inline templates (which do update for both Docs and Canvas) and not having the extra overhead of defining the component in components:{...}, then writing out the component in the template string, then binding all the props. Using the render function all this is removed and I can just use the example.vue and any other .vue file as-is and pass the props object in like so:

... other imports ...

import StackedBasic from "./StackedBasic.vue";
import StackedBasicSrc from "!!html-loader!./StackedBasic.vue";

... define default arg types ...

<Meta title="Components/Cards/Stacked" argTypes={defaultArgTypes} />
// helper function
export const WrapComponent = (Component, props) => ({
	props: Object.keys(props),
	render: (h) => h(Component, { props }),
});

### Basic Card

<Canvas>
	<Story
		name="Basic Card"
		height="500px"
		parameters={{ storySource: { source: StackedBasicSrc } }}
		args={{ shadow: "shadow-md", title: "Card Titled" }}
	>
		{(args) => WrapComponent(StackedBasic, args)}
	</Story>
</Canvas>

<ArgsTable story="Basic Card" />

With this setup, we can build out multiple component examples as normal .vue files and reuse the WrapComponent passing in props in one go, which is handy since we can also use html-loader to pull in the source for the example and show it in the "show code" panel for a full view into the vue component usage.

The only problem is that Canvas doesn't update when controls are changed :(

Any help here would be much appreciated!

@shilman
Copy link
Member

shilman commented Sep 3, 2020

@subhaze sorry my vue knowledge is pretty poor. maybe @backbone87 or @Aaron-Pool can give a hand?

@subhaze
Copy link

subhaze commented Sep 3, 2020

OK thanks, I just wasn't sure if it was a limitation or expected behavior on Storybooks side to where you have to define components via template: '<component-here :a-prop="aProp" /> instead of a render function render: (h) => h(ComponentHere, {props}) for Canvas to update the component when changing control values.

@shilman
Copy link
Member

shilman commented Sep 5, 2020

I don't know the details, but we basically declare the names of the props we want like this:

https://github.com/storybookjs/storybook/blob/next/examples/vue-kitchen-sink/src/stories/addon-controls.stories.js#L19

Then @storybook/vue reactively updates those props behind the scenes when the arg values change. We have examples of consuming those props using a template. I don't know enough about vue to know whether anything special is needed for render functions.

@rezkypg
Copy link

rezkypg commented Oct 21, 2020

Sorry I just want to make sure, do you already have workaround on this @subhaze ?
Currently I have the same exact problem as yours, even though I define components via template: '<component-here :a-prop="aProp" />.

@subhaze
Copy link

subhaze commented Oct 22, 2020

@rezkypg sadly no, I've been noticing at times stories not updating on control changes; A refresh works at times. But as my work around I'm just using a helper function that takes props and generates a template string with all the props in-lined.

@rezkypg
Copy link

rezkypg commented Oct 22, 2020

Hoo I see. Thanks for the info @subhaze

@jwir3
Copy link

jwir3 commented Jan 26, 2021

I'm not sure if this is the same issue, but I've noticed that sometimes components, such as the one below:

import React from 'react';

import { SchedulePhase } from '../../';

export default {
  title: '03-Cells/SchedulePhase',
  component: SchedulePhase,
  argTypes: {
    timeUnit: {
      control: {
        type: 'select',
        options: [
          'years',
          'months',
          'weeks',
          'days',
          'hours',
          'minutes'
        ]
      }
    }
  }
};

const Template = (args) => <SchedulePhase {...args} />;

export const Default = Template.bind({});
Default.args = {
  phaseName: 'Prep',
  timeAmount: 2,
  timeUnit: 'hours'
};

Don't update on the Canvas view, but they do update on the Docs view. Moreover, in the above example, phaseName updates on the Canvas view, as expected, but the other two - timeAmount and timeUnit do not.

@cherylcarpenter
Copy link

why is this closed? What is the workaround?
I am experiencing this as described by @jwir3

@shilman
Copy link
Member

shilman commented Oct 12, 2021

@cherylcarpenter any chance you can open a new issue and provide a reproduction?
See how to create a repro. Thank you! 🙏

@rickyruiz
Copy link

why is this closed? What is the workaround? I am experiencing this as described by @jwir3

The workaround for me back then was to add a random key to the component to always enforce an update.

const Template: Story = (args, { argTypes }) => {
  return defineComponent({
    props: Object.keys(argTypes),
    setup(props) {
      return () =>
        h(
          BaseButton,
          {
            key: Math.random(),
            props,
          },
          ['Button']
        )
    },
  })
}

@jwir3
Copy link

jwir3 commented Oct 13, 2021

@cherylcarpenter Yes, as @rickyruiz mentioned, I force a re-render by adding a random key. I have a slightly more complicated method that resets when I want to force a re-render but not when I don't care about it rendering, as in situations where backend information is being computed that has no visual aspect to re-render, but it's essentially the same. (I should probably refactor this stuff out of my component, anyway, haha)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

9 participants