diff --git a/addons/docs/docs/multiframework.md b/addons/docs/docs/multiframework.md index bb628db839cc..f2148511e5f0 100644 --- a/addons/docs/docs/multiframework.md +++ b/addons/docs/docs/multiframework.md @@ -6,6 +6,7 @@ Storybook Docs [provides basic support for all non-RN Storybook view layers](../ - [Arg tables](#arg-tables) - [Component descriptions](#component-descriptions) - [Inline story rendering](#inline-story-rendering) +- [Dynamic source rendering](#dynamic-source-rendering) - [More resources](#more-resources) ## Framework-specific configuration @@ -103,6 +104,59 @@ addParameters({ The input is the story function and the story context (id, parameters, args, etc.), and the output is a React element, because we render docs pages in react. In the case of Vue, all of the work is done by the `@egoist/vue-to-react` library. If there's no analogous library for your framework, you may need to figure it out yourself! +## 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. + +This dynamic rendering is framework-specific, meaning it needs a custom implementation for each framework. + +Let's take a look at the React framework implementation of `dynamic` snippets as a reference for implementing this feature in other frameworks: + +```tsx +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; +}; +``` + +A few key points from the above snippet: + +- The **renderJsx** function call is responsible for transforming the output of a story function into a string specific to the framework (in this case React). +- The returned snippet string is emitted on Storybook's channel through **channel.emit()** and subsequently consumed up by the Source block for any given story, if it exists. + +
+ To learn more and see how it's implemented in context, check out the code . +
+ +Now we need a way to configure how it's displayed in the UI: + +```tsx +import { jsxDecorator } from './jsxDecorator'; +export const decorators = [jsxDecorator]; +``` + +This configures the `jsxDecorator` to be run on every story. + +
+ To learn more and see how it's implemented in context, check out the code . +
+ ## More resources - References: [README](../README.md) / [DocsPage](docspage.md) / [MDX](mdx.md) / [FAQ](faq.md) / [Recipes](recipes.md) / [Theming](theming.md) / [Props](props-tables.md) diff --git a/docs/frameworks.js b/docs/frameworks.js index b9e92ba0f1a1..6bf0e9f75be2 100644 --- a/docs/frameworks.js +++ b/docs/frameworks.js @@ -109,6 +109,11 @@ module.exports = { unsupported: [], path: 'writing-docs/doc-blocks#source', }, + { + name: 'Dynamic source', + supported: ['react'], + path: 'writing-docs/doc-blocks#source', + }, { name: 'Args Table', supported: ['react', 'vue', 'angular', 'html', 'ember', 'web-components'], diff --git a/docs/writing-docs/doc-blocks.md b/docs/writing-docs/doc-blocks.md index 29e86d761568..00faddd48439 100644 --- a/docs/writing-docs/doc-blocks.md +++ b/docs/writing-docs/doc-blocks.md @@ -4,7 +4,6 @@ title: 'Doc Blocks' Doc Blocks are the building blocks of Storybook documentation pages. By default, [DocsPage](./docs-page.md) uses a combination of the blocks below to build a page for each of your components automatically. - Custom [addons](../api/addons.md) can also provide their own doc blocks. ## ArgsTable @@ -150,6 +149,14 @@ To customize the source snippet that’s displayed for a story, set the `docs.so +There is also a `docs.source.type` parameter that controls how source is auto-generated. Valid values include: + +| Value | Description | Support | +| :----------------- | :------------------------------------------------------------------------------------------------------------------ | :------------------------------------------: | +| **auto** (default) | Use `dynamic` snippets if the story is written using [Args](../writing-stories/args) and the framework supports it. | All | +| **dynamic** | Dynamically generated snippet based on the output of the story function, e.g. JSX code for react. | [Limited](../api/frameworks-feature-support) | +| **code** | Use the raw story source as written in the story file. | All | + ### MDX You can also use the `Source` block in MDX. It accepts either a story ID or `code` snippet. Use the `language` for syntax highlighting.