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

Add clarifcation in Docs regarding Magic bahvior when using Vue & action #17849

Open
minseoksuh opened this issue Apr 1, 2022 · 5 comments
Open

Comments

@minseoksuh
Copy link

Is your feature request related to a problem? Please describe
A clear and concise description of the problem. E.g. I'm always frustrated when [...]

When using Vue with storybook
the storybook is automatically adding 'on' prefix to emitted events.
Is this behavior offically documented anywhere?
If not, I think it should be more explicitly documented.

For example,
I am making a component that emits

const emit = defineEmits<{(e: "click"): void; (e: "delete"): void }>();

defining story

export default {
  title     : "Example/tag",
  ...
  argTypes : {
    ...
    click  : { action: "click" },
    delete : { action: "delete" },
  },
};

like this does not work.

I have to add on and make it camelCase

export default {
  title     : "Example/tag",
  ...
  argTypes : {
    type : {
      control : { type: "inline-radio" },
      options : [undefined, ...Object.values(TAG_TYPE)],
    },
    onClick  : { action: "click" },
    onDelete : { action: "delete" },
  },
};

like this. To actually connect actions to click and delete event.

Is storybook doing this by default?
This may lead to strange cases like below.

const emit = defineEmits<{(e: "onClick"): void; (e: "onDelete"): void }>();

export default {
  title     : "Example/tag",
  ...
  argTypes : {
    type : {
      control : { type: "inline-radio" },
      options : [undefined, ...Object.values(TAG_TYPE)],
    },
    onOnClick  : { action: "click" },
    onOnDelete : { action: "delete" },
  },
};

Please let me know if I missed something.

Thanks

Describe the solution you'd like
What would you like to see added to Storybook to solve problem?

Describe alternatives you've considered
Any alternative solutions or features you've considered.

Are you able to assist to bring the feature to reality?
no | yes, I can...

Additional context
Add any other context or screenshots about the feature request here.

@shilman
Copy link
Member

shilman commented Apr 1, 2022

Documented here: https://storybook.js.org/docs/react/essentials/actions#automatically-matching-args

If you have suggestions for how to improve the documentation or make it more discoverable, please let us know!

@minseoksuh
Copy link
Author

@shilman
Thank you for fast response.

However, I dont think we are talking about the same issue.
https://storybook.js.org/docs/react/essentials/actions#automatically-matching-args

means that any argTypes that starts with on and a Capital letter will be recognized by Storybook as action.
that is why

export default {
  title     : "Example/switch",
  component : SwitchVue,
  ...
  argTypes : {
    onChange : { },
  },
};

onChange above becomes action without explicitly stating that it is.


However, what I am talking about is that

emitted events in Vue does not retain its original name in storybook as argType.

const emit = defineEmits<{ (e: "click"): void; (e: "delete"): void }>();

Screen Shot 2022-04-04 at 7 35 28 PM

like above emitted events gets registered in control by their original name click and delete

However,
in order to register them as action

export default {
  title     : "Example/tag",
  ...
  argTypes : {
    ...
    click  : { action: "click" },
    delete : { action: "delete" },
  },
};

this does not work.

I have to change it as

export default {
  title     : "Example/tag",
  ...
  argTypes : {
    type : {
      control : { type: "inline-radio" },
      options : [undefined, ...Object.values(TAG_TYPE)],
    },
    onClick  : { action: "click" },
    onDelete : { action: "delete" },
  },
};

to register them as actions.

And this is not a behavior that is described in the link you gave me.

I will be more than happy to make a PR if the strange behavior I am talking about is something you also recognize as such.
(If I do make a PR, I think it should only be for vue as it is only relevent there)

Hope we can be on the same page.
Please let me know if I am thinking wrong.

Thanks

@shilman
Copy link
Member

shilman commented Apr 4, 2022

@minseoksuh This sounds like a bug to me. Do you a have a reproduction repo you can share? If not, can you create one? See how to create a repro.

@minseoksuh
Copy link
Author

minseoksuh commented Apr 11, 2022

@shilman
Sorry for the late response.
https://6253c645894baa003ae23ddd-pmuysumcby.chromatic.com/?path=/story/example-button2--primary

Here is the reproduction.

  1. Created a project using npx sb@next repro with vue3 setting
  2. Copied already existing Button.stories.js to make Button2.stories.js
  3. Changed arg types in Button2.stories.js to use emitted name click
  4. Storybook action does not work for Button2.stories, but does work for Button.stories, which uses 'onClick' instead of 'click' for argTypes.

I don't think this is a behavior storybook was not aware of.
My guess is that this happens so Vue component can emulate React style of component.

What I am saying, is since storybook automatically adds on prefix (and since there is no official mentioning of this behavior) maybe add a little note in

https://storybook.js.org/docs/vue/essentials/actions

something like

When using Vue, make sure to add on to and camelCase your emit name to connect the event to action.
For example, click event should be onClick and update:modelValue should be onUpdate:modelValue in argTypes

Thanks again.

@hyshka
Copy link

hyshka commented Jun 19, 2023

I think this is what we'll be doing until this is better supported.

argTypes: {
  onClick: { action: 'click', table: { disable: true, }, },
  'onUpdate:modelValue': { action: 'update:modelValue', table: { disable: true, }, },
},

This will remove the onClick control from the table so that the actual click event is displayed in the control table in the events category.


  1. "In Vue 3's virtual DOM, event listeners are now just attributes, prefixed with on ..." source

  2. Adding onClick as an argType is the equivalent of adding @click="args.click" within the template property of the render function. So, it's really just a shortcut but is confusing because it doesn't mesh intuitively with Vue. With this in mind, both of the following examples should be equivalent:

    a. Use the onClick syntax in argTypes but hide them from the controls table.

    argTypes: {
         onClick: {
             action: 'click',
             table: {
                 disable: true,
             },
         },
    },
    

    b. Manually define all actions in argTypes and within the render function template:

    argTypes: {
         show: {
             action: 'click',
         },
    },
    render: (args) => ({
        components: { MyComponent },
        setup() { return { args }; },
        template: `<MyComponent v-bind="args" @show="args.click">`,
    },
    

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

4 participants