storybook: Addon-docs: Show source block with generated knob values

Describe the bug

I’m using addon-knobs along with addon-docs, and I’m having a hard time getting the two to work well together.

Within my Component.stories.mdx file I have the following:

export const defaultProps = (selected, icon) => ({
  selected: boolean('selected', false),
  label: text('label', 'Essentials'),
  description: text(
    'description',
    'This s a description.'
  ),
});

<Preview>
  <Story name="default">
    <Box
      {...defaultProps(false)}
    />
  </Story>
</Preview>

I’m using defaultProps as a helper function for all of my stories in the mdx file as they all share the same props. The problem I have is that when this renders in the Storybook docs page it shows the function call instead of all of the props.

Screen Shot 2019-10-08 at 10 47 56 AM

If i don’t use a function to generate these, I still see the addon-knobs function call instead of the actual prop value.

Screen Shot 2019-10-08 at 10 48 55 AM

To Reproduce

  1. Create a mdx story with addon-knobs.
  2. Observe that any created story ends up having the addon-knobs function call instead of the value the functions return.

Expected behavior

I’d expect it to show the actual prop values. For example:

<Box selected={true} label="The label" />

Is there a correct way to do this? With the way it works currently it’s hard to define stories inside of the mdx file exclusively.

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Reactions: 14
  • Comments: 47 (15 by maintainers)

Most upvoted comments

To whet your appetite:

csf stories with properties (aka knobs): https://github.com/atanasster/storybook/blob/properties-2/examples/official-storybook/stories/addon-controls/props-editors.stories.js

mdx stories with properties (aka knobs): https://github.com/atanasster/storybook/blob/properties-2/examples/official-storybook/stories/addon-controls/propeditors.stories.mdx

It should make it into the 6.0 alphas by mid-february and we would love to get testing and feedback for it, especially you guys have been at it for some time already.

and a screenshot of the source code preview for this story:

export const textDefaultProp = ({ text }) => text;
textDefaultProp.story = {
  properties: {
    text: 'Hello',
  },
};

grab42

Just include withKnobs in the Meta decorators and knobs work same as they do in CSF. <Meta title="Desktop|Image Gallery" component={ImageGallery} decorators={[withKnobs]} />

Yes, that would be the goal, sth


<Preview>
  <Story name="all checkboxes" properties={knobs}>
      {({ disabled, label }) => <button disabled={disabled}>{label}</button>}
  </Story>
</Preview>;

@JamesIves and other participants - you make great points. We are adding to the csf story format, and with sb6+ the properties(knobs) will be created in a declarative way and without any addon code in the story, so this should address your main concerns. here’s how you would write your knob’ed stories in 6.0:

export const selectPropStory = ({ label, color, backgroundColor }) => (
  <Button color={color} backgroundColor ={backgroundColor}>{label}</Button >
);

Additionally, we can add a second tab to the <Soure /> preview component to display the raw html code, maybe even a dom-type explorer for the story - what you think?

@liamross #6639 is coming, probably in a 6.x release.

Just bringing up my question again, not sure if anyone has this information:

“I am wondering if there are any plans to allow you to set knobs within docs without having to go back to canvas?”

This is still valuable to fix.

Yeah this is still broken on version 5.3.0-rc.12, even after adding groupId. I have a button component with some simple props and this is what I get in the docs “Show code” expandable:

() => (
<Button
  disabled={boolean('disabled', false, '_')}
  onClick={action('onClick')}
>
  {text('children', 'Button content', '_')}
</Button>
)

For reference, here’s my Button.stories.tsx file:

import { action } from '@storybook/addon-actions';
import { boolean, text } from '@storybook/addon-knobs';
import React from 'react';
import Button from '../Button';
import docs from './README.md';

export default { title: 'Button', component: Button, parameters: { info: docs } };

export const Basic = () => (
  <Button
    disabled={boolean('disabled', false, '_')}
    onClick={action('onClick')}
  >
    {text('children', 'Button content', '_')}
  </Button>
);

Also, while I’m here, I am wondering if there are any plans to allow you to set knobs within docs without having to go back to canvas? Between this issue and the knobs not being within docs, It is making me strongly consider removing story previews from docs entirely since they provide minimal value (non configurable and with broken code previews)

I was inquiring about roughly this issue in Discord the other night—it appears that knobs with the same label act something like singletons in Docs mode, and the first default value that’s defined is used for all components in the Docs tab. Adding a groupId is a nice idea and worked for me just now on 5.3.0-beta.31.

For anybody who is interested in Controls but don’t know where to start, I’ve created a quick & dirty step-by-step walkthrough to go from a fresh CRA project to a working demo. Check it out:

=> Storybook Controls w/ CRA & TypeScript

There are also some “knobs to controls” migration docs in the Controls README:

=> How do I migrate from addon-knobs?

Looks like the links @atanasster are to an experimental “addon-controls” addon that was removed. See the commit history in properties-2 branch.

The removed code is here: https://github.com/atanasster/storybook/tree/4a62e69ecb82fbfc19c65c834309a93e50de0fe7/examples/official-storybook/stories/addon-controls

I don’t know what the plans are for this but it sounds nice 😃

Side note: It would be amazing if the knobs / controls could be generated from prop types, similar to how the props table is.

@shilman nice one for the issue rename. “Show source block with generated knob values” is exactly what we need i think.

Hi gang, We’ve just released addon-controls in 6.0-beta!

Controls are portable, auto-generated knobs that are intended to replace addon-knobs long term.

Please upgrade and try them out today. Thanks for your help and support getting this stable for release!

@flynnham you can still use no-arg functions in 6.0. in a future iteration of the source block we will show the live values in the code per this issue so you can copy and paste it.

Story:

const Basic = ({ label }) => <Button label={label} />

Raw display:

({ label }) => <Button label={label} />

Values display:

({ label }) => <Button label="actual label" />

Hi everyone! Seems like there hasn’t been much going on in this issue lately. If there are still questions, comments, or bugs, please feel free to continue the discussion. Unfortunately, we don’t have time to get to every issue. We are always open to contributions so please send us a pull request if you would like to help. Inactive issues will be closed after 30 days. Thanks!

Adding a groupId (third parameter) to knobs solved this for me.

Each should be unique.

text('Text', basic, 'basic')

I’m seeing the same thing with CSF stories. If the prop is set by a knob then it looks like its using the component’s default value instead of what the knob says.

Great Caesar’s ghost!! I just released https://github.com/storybookjs/storybook/releases/tag/v6.0.0-beta.38 containing PR #11332 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.

@AnnyCaroline Yup. I’ll probably implement the improved source rendering in 6.1 based on the controls work (NOT the knobs package, which will be deprecated at some point in the future), so I felt it was relevant to share the progress.

The biggest reason we have to separate the two out is mostly due to how the preview code gets generated. As knobs require a function the value gets rendered in the preview as that, instead of what the result of that function produces.

<Dropdown label={text('label', 'Default')} />

In our markdown file we generate document specific versions that have more context around why they are being displayed that don’t use knobs to prevent this problem. In the example above I’d expect label to look like this:

<Dropdown label="Default" />

When you combine that with a helper function that generates a series of default props the code examples end up looking really messy. The same thing happens with the InVision integration:

<DollarCircleIllustration {...defaultProps(false, false, false)} />

I’d love for there to be an easy way to generate clean code previews as that will prevent a bunch of repetition on our end. I’d also love for there to be an easy way to generate stories that are defined in the .mdx file, but hidden from the Docs tab so they only appear in the canvas.

I still don’t see the point of having Knobs UI in Docs. Would it still be an add-on tab? Would it be one set of knobs that controls all the stories with Knob params or would a Knob UI need to be appended to every story? Why not include a few more stories showing the important variations? I’m not saying it’s pointless, just doesn’t seem like a high priority.

For me at least It’s not so much about making the knobs visible in the docs so much as it’s making the previews that are generated as an outcome useful. Otherwise you end up with a bunch of component previews with business logic in them.

Originally we wanted to define all of our stories in our docs (still using Canvas for addons) but we had to move away from that approach in favor of the storiesOf api to make this work correctly. Now we define our stories in the story.js file, and we setup repeated examples in the .mdx file. Admittedly this works well, but it’s not entirely future proofed I feel.

https://github.com/UnitedIncome/components/tree/develop/components/molecules/Cabinet

Just bringing up my question again, not sure if anyone has this information:

“I am wondering if there are any plans to allow you to set knobs within docs without having to go back to canvas?”

I think it is a good idea to keep docs for documentation and isolate the canvas to manipulate the component. but may be one canvas for all the stories of the same component.

@arfa yep, that works if you want to exclude the whole file from docs, not just an individual story.

Can also confirm what @liamross is saying. My approach has been to write new stories, without knobs, that speicfically target the docs page code previews. Then include a knobs story to be access by developers, in the canvas tab, that I exclude from the docs:

export const basic = () => (
  <Image alt="Kitten" src="http://placekitten.com/800/432" />
);

export const knobs = () => (
  <Image
    alt={text('alt', 'Kitten')}
    src={text('src', 'http://placekitten.com/800/432')}
  />
);

knobs.story = { parameters: { docs: { disable: true } } };

This works pretty well, but would not be necessary if the code previews showed the default values specifed by the knobs functions.

Adding a groupId (third parameter) to knobs solved this for me.

Each should be unique.

text('Text', basic, 'basic')

Which version of knobs are you using? This workaround doesn’t seem to work for me. In the Canvas view it looks correct, but not in the Docs view.