storybookjs / storybook

Storybook is the industry standard workshop for building, documenting, and testing UI components in isolation
https://storybook.js.org
MIT License
84.64k stars 9.31k forks source link

[Bug]: `of` prop doesn't seem to work #22451

Closed herzaso closed 1 year ago

herzaso commented 1 year ago

Describe the bug

I've created a custom DocBlock that just wraps around Canvas passing it the prop of with a single story of another component, and I get an exception: Invalid value passed to the 'of' prop. The value was resolved to a 'component or unknown' type but the only types for this block are: story

To Reproduce

https://github.com/herzaso/test-storybook/tree/of_prop

System

Environment Info:

  System:
    OS: macOS 12.6
    CPU: (10) arm64 Apple M1 Max
  Binaries:
    Node: 18.7.0 - /private/var/folders/pm/h3p3r0cn09g7fdbxv7mr04g00000gn/T/xfs-f77dda46/node
    Yarn: 3.3.1 - /private/var/folders/pm/h3p3r0cn09g7fdbxv7mr04g00000gn/T/xfs-f77dda46/yarn
    npm: 8.15.0 - /opt/homebrew/bin/npm
  Browsers:
    Chrome: 112.0.5615.137
    Safari: 16.0

Additional context

No response

JReinhold commented 1 year ago

This is an interesting issue, thanks for the reproduction!

This isn't a use case that we had envisioned, but I'm surprised it doesn't work.

I was able to "fix" the issue by using the <MyBlock /> in an MDX file, and then importing the Headers.LoggedIn story in that MDX file. I didn't even need to pass it in as a prop, I just needed to import it to make it work. This doesn't actually solve the issue since you want to add it to the global DocsPage in preview.tsx instead - but it does give a hint to what's going on.

It seems like it is using the story reference before the story is initialised in the store, so it can't find it. Importing the story in an MDX file makes the story store load it before the doc.

@tmeasday would you happen to know what is going on here, why you can't just reference a story in a block directly, but it has to be imported in an MDX file first? There relevant parts of the reproduction are these files: https://github.com/herzaso/test-storybook/blob/of_prop/src/stories/MyBlock.tsx https://github.com/herzaso/test-storybook/blob/of_prop/.storybook/preview.tsx https://github.com/herzaso/test-storybook/blob/of_prop/src/stories/Header.stories.ts

@herzaso can you share a bit what your use case is, and what you're trying to achieve with this? The of prop was meant as a way to pass in references in docs, but it seems like you're trying to show a Canvas with the same story for all docs pages?

herzaso commented 1 year ago

@JReinhold I'm trying to create a related-components section (DocBlock) so for example, in the Button docs you might see IconButton and ButtonGroup as related componenets - this section will show the name and descripion of the related component and a Canvas with the primary story

tmeasday commented 1 year ago

To make all this stuff work we need to know (statically, as part of the story index) which CSF files are used by a given MDX page. You'll see a field in index.json called storiesImports that contains that info, which is obtained by parsing the .mdx file and looking for imports of CSF files.

So yeah, if you transitively import a CSF file like you are here, that's not going to work, leading to the problem you are seeing.

I would say this is just a limitation of the architecture and you'll need to find a way to work around it.

herzaso commented 1 year ago

@tmeasday The only way around it is to turn autodocs off and create an MDX file for every component?

tmeasday commented 1 year ago

@herzaso how would the related component section know which related components to list?

herzaso commented 1 year ago

@tmeasday in a manual MDX doc, I can import the stories in the MDX file and pass them as an of prop to a custom Related component which will use useOf to extract the data. With autodocs, I don't have an MDX file and so I must import the stories from the stories.ts file - which you indicated that it wouldn't work

tmeasday commented 1 year ago

@herzaso I guess I mean I am wondering how the autodocs template, which I assume would use the "related components" block you mentioned, would know which related components to use?

herzaso commented 1 year ago

@tmeasday my initial thought was to use the @see tag in the comments but since you strip everything except for the description, I reverted to using the meta parameters, so I import the stories in my component stories file and assign them to an array in its meta parameters struct

tmeasday commented 1 year ago

Yes, so that's unfortunate @herzaso. I think perhaps opening a feature request for this use case (referencing other CSF files in a CSF file and being able to reference those stories in the autodocs template) is a good idea. It's not something we support and it's not super simple to support, but I see the utility.

herzaso commented 1 year ago

@tmeasday done, thanks

JReinhold commented 1 year ago

Closing in favor of #22549