-
-
Notifications
You must be signed in to change notification settings - Fork 9.3k
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-docs: Document dynamic source snippets #12530
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@shilman sorry for taking a bit longer in taking a look at the pull request. I've left a comment regarding this pull request, let me know if you're ok with it, or if we need to adjust the wording a bit more.
Thanks in advance
addons/docs/docs/multiframework.md
Outdated
## Dynamic source rendering | ||
|
||
Starting in 6.0 there are several modes of rendering stories in the [Source doc block](https://storybook.js.org/docs/react/writing-docs/doc-blocks#source). The `dynamic` source type renders a snippet based on the output of a story function. For example React | ||
s `dynamic` snippets are JSX reconstructed based on the React node. | ||
|
||
Since this dynamic rendering is framework-specific, it must be added to each framework. Here we dissect the React framework implementation as a reference for implementing this feature in other frameworks. | ||
|
||
Here are the key lines of the [React preview config](https://github.com/storybookjs/storybook/blob/next/addons/docs/src/frameworks/react/config.ts): | ||
|
||
```ts | ||
import { jsxDecorator } from './jsxDecorator'; | ||
export const decorators = [jsxDecorator]; | ||
``` | ||
|
||
This function gets run on every story. Diving into [its implementation](https://github.com/storybookjs/storybook/blob/next/addons/docs/src/frameworks/react/jsxDecorator.tsx): | ||
|
||
```ts | ||
import { addons, StoryContext } from '@storybook/addons'; | ||
import { SNIPPET_RENDERED } from '../../shared'; | ||
|
||
export const jsxDecorator = (storyFn: any, context: StoryContext) => { | ||
const story = storyFn(); | ||
|
||
// We only need to render JSX if the source block is actually going to | ||
// consume it. Otherwise it's just slowing us down. | ||
if (skipJsxRender(context)) { | ||
return story; | ||
} | ||
|
||
const channel = addons.getChannel(); | ||
|
||
const options = {}; // retrieve from story parameters | ||
const jsx = renderJsx(story, options); | ||
channel.emit(SNIPPET_RENDERED, (context || {}).id, jsx); | ||
|
||
return story; | ||
}; | ||
``` | ||
|
||
The `renderJsx` function is a react-specific function that takes the output of a story function and converts it into a framework-appropriate string. The resulting value is emitted on Storybook's channel and subsequently consumed up by the Source block for that story, if one exists. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@shilman we have room for improvements here we could probably go with something along these lines:
## Dynamic source rendering
With the release of Storybook 6.0, we've improved how stories are rendered in the [Source doc block](https://storybook.js.org/docs/react/writing-docs/doc-blocks#source). One of such improvements is the `dynamic` source type, which renders a snippet based on the output the story function.
Before we take a look at a concrete example, we would like to remind you that this is framework-specific and you'll need to make the necessary adjustments depending on which framework you're working with.
With that out of the way, let's take a look on how the `dynamic` snippets work with React:
// addons/docs/src/frameworks/jsxDecorator.tsx code example
Taking a closer look at the code snippet above, a couple of things worth mentioning:
- The **renderJsx** function call, as it's responsible for transforming the output of a story function into a string specific to the framework (in this case React).
- The returned value of the function above is emitted on Storybook's channel through **channel.emit()** and subsequently consumed up by the Source block for any given story, if it exists.
<div class="aside">
If you want to learn more and see how it's implemented take a look <a href="https://github.com/storybookjs/storybook/blob/next/addons/docs/src/frameworks/react/jsxDecorator.tsx">here</a> .
</div>
Now we'll need a way to configure how it's displayed in the UI. You can use a similar approach to the one below to achieve it:
// addons/docs/src/frameworks/react/config.ts code example
<div class="aside">
For brevity purposes we've only included the relevant information. Take a look <a href="https://github.com/storybookjs/storybook/blob/next/addons/docs/src/frameworks/react/config.ts">here</a> for the full implementation.
</div>
We would like to point out that the `jsxDecorator` function will be executed for each story.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @jonniebigodes ! I've updated it to the new structure, with a few tweaks
Addon-docs: Document dynamic source snippets
Issue: N/A
What I did
Document dynamic source snippets
Related #11588 #11400 #8672
How to test
N/A