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

documentation: Clarify description of args - Add example of args controlling more than props #13978

Merged
merged 5 commits into from
Mar 2, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions docs/snippets/common/page-story-slots.js.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
```js
// Page.stories.js

import Page from './Page.vue';

export default {
title: 'Page',
};

const Template = (args, { argTypes }) => ({
components: { Page },
props: Object.keys(argTypes),
template: `
<page v-bind="$props">
<footer v-if="footer" v-slot=footer v-html="footer"/>
</page>
`,
});

export const CustomFooter = Template.bind({});
CustomFooter.args = {
footer: '<a href="https://storybook.js.org/">Built with Storybook</a>',
};
```
2 changes: 2 additions & 0 deletions docs/snippets/vue/button-story-with-args.js.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ export default { title: 'Components/Button' };
const Template = (args, { argTypes }) => ({
components: { Button },
props: Object.keys(argTypes),
// Storybook provides all the args in a $props variable.
// Each arg is also available as their own name.
saschwarz marked this conversation as resolved.
Show resolved Hide resolved
template: '<Button v-bind="$props" v-on="$props" />',
});

Expand Down
24 changes: 19 additions & 5 deletions docs/writing-stories/args.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: 'Args'
---

A story is a component with a set of arguments (props, slots, inputs, etc). “Args” are Storybook’s mechanism for defining those arguments as a first class entity that’s machine readable. This allows Storybook and its addons to live edit components. You _do not_ need to change your underlying component code to use args.
A story is a component with a set of arguments that define how the component is to be rendered. “Args” are Storybook’s mechanism for defining those arguments in a single JavaScript object. Args can be used to dynamically change props, slots, styles, inputs, etc. This allows Storybook and its addons to live edit components. You _do not_ need to change your underlying component code to use args.

When an arg’s value is changed, the component re-renders, allowing you to interact with components in Storybook’s UI via addons that affect args.

Expand Down Expand Up @@ -98,6 +98,20 @@ Args are useful when writing stories for composite components that are assembled

<!-- prettier-ignore-end -->

## Args can modify any aspect of your components
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we make the prose more framework agnostic? This text gets displayed to all frameworks (only the code samples change).

Also, how would this work in React?

Copy link
Contributor Author

@saschwarz saschwarz Feb 20, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I realize that, but I don't know enough about React to know how you'd use args other than as props. And that was the problem that I was trying to address: frameworks that have concepts like slots that don't exist in React (AFAIK).

The original text was very props-centric and lead to my (and others) questions about slots in discord.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Couldn't React be done like this?

const Template = (args, { argTypes }) => (
     <page {...args}>
       {args.footer}
     </page>
);

 export const CustomFooter = Template.bind({});
 CustomFooter.args = {
   footer: <a href="https://storybook.js.org/">Built with Storybook</a>,
 };

A little sloppy, but I think that is the equivalent "args as a child" concept. How can we frame those both in this?

Copy link
Contributor Author

@saschwarz saschwarz Feb 20, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If there isn't a snippet for every framework, what do I do? Do I copy the React version to the common and all the other supported frameworks?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Arg values have to be telejson serializable @phated so that example won't work. Hopefully we can mitigate that limitation with #13888

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would this (simpler) example be valid for React? Do the examples have to do exactly the same thing for all frameworks?

const Template = (args, { argTypes }) => (
     <page {...args}>
       <footer>{args.footer}</footer
     </page>
);

 export const CustomFooter = Template.bind({});
 CustomFooter.args = {
   footer: 'Built with Storybook',
 };

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The examples have to do approximately the same thing.

The code will necessarily be different but the technique should be similar. The code snippet for each framework can be as verbose as we need to accomplish the technique.

Copy link
Contributor Author

@saschwarz saschwarz Feb 22, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@domyen If there isn't a snippet for every framework, what do I do?

  1. Do I copy the React version to the common?
  2. Copy React version to all the other supported frameworks?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@saschwarz Add snippets for Vue and React 🙏

All the other frameworks will automatically be shown React until someone contributes the code sample. There's a call to action to do this built into the snippet component already.


Args can be used in your story templates to configure your component just as you would in an application. Here’s an example of how a `footer` arg can be used to populate a named slot in a Vue component.

<!-- prettier-ignore-start -->

<CodeSnippets
paths={[
'common/page-story-slots.js.mdx',
]}
/>

<!-- prettier-ignore-end -->

## Setting args through the URL

Initial args for the currently active story can be overruled by setting the `args` query parameter on the URL. Typically, you would use the Controls addon to handle this automatically, but you can also manually tweak the URL if desired. An example of Storybook URL query params could look like this:
Expand Down Expand Up @@ -145,7 +159,7 @@ In Storybook 5 and before we passed the context as the first argument. If you’

<!-- prettier-ignore-start -->

<CodeSnippets
<CodeSnippets
paths={[
'common/storybook-preview-parameters-old-format.js.mdx'
]}
Expand All @@ -154,8 +168,8 @@ In Storybook 5 and before we passed the context as the first argument. If you’
<!-- prettier-ignore-end -->

<div class="aside">
Note that `args` is still available as a key on the context.

Note that `args` is still available as a key on the context.

saschwarz marked this conversation as resolved.
Show resolved Hide resolved
</div>
</details>