Custom documentation pages for storybookjs

Overview

custom documentation pages in storybook

Demo sites

Background

  1. Circumvent the hard-coded docs render.
    docs pages need to reside in the `preview` part of Storybok in order to render stories (since that’s where the stories render functions reside), while the TAB addons are placed in the `manager` part of storybook. Since the manager and the preview reside in different bundles, only JSON-compatible data is available to any code residing in the manager, thus any functions are not available.
  2. Circumvent the hard-coded DOM elements
    documentation pages that render stories need to reside inside the preview `iframe` in order to render stories in a custom `docs` page and prevent css styles leaking into the story functions, while regular storybook `TAB`-type addons are rendered outside the `iframe`.

Step by step guide

  • Getting started
yarn add @component-controls/storybook-custom-docs
module.exports = {
...
addons: [
...
{
name: '@component-controls/storybook-custom-docs',
options: {
//configure an array of the pages to display
pages: [require.resolve('./page-story.js')]
},
}
],
};
  • Page templates
{
//the url path for the page. e.g: 'page'
key: string,

//the tab title. e.g: 'My Pages'
title: string,

//render function, return your custom page here.
render: ({ active }) => React.ReactNode,
}

Examples

  1. From component-controls/pages
import React from 'react';
import { ClassicPage } from '@component-controls/pages';
import { DocsContainer } from '@component-controls/storybook';
export default {
key: 'page',
title: 'Page',
render: ({ active }) => active ? (
<DocsContainer active={active}>
<ClassicPage />
</DocsContainer>
): null,
};
component-controls page template
import React, { createElement }  from 'react';
import { useContext } from '@component-controls/storybook-custom-docs';
const CustomPage = () => {
const context = useContext();
return (
<div>
<h1>Simple docs page</h1>
{createElement(context.storyFn)}
</div>
);
}
const page = {
key: 'custom',
title: 'Simple Page',
render: ({ active }) => active ? <CustomPage /> : null,
}
export default page;
custom story render
import React from 'react';import { DocsContainer, Story, Preview, Source, Title } from '@storybook/addon-docs/blocks';
import { useContext } from '@component-controls/storybook-custom-docs';
const Page = () => {
const context = useContext();
return (
<DocsContainer context={context}>
<Title>Using storybook docs page blocks</Title>
<Preview>
<Story id="." />
</Preview>
<Source id="." />
</DocsContainer>
);
}
const page = {
key: 'docs-page',
title: 'Docs blocks',
render: ({ active }) => active ? <Page /> : null}
export default page;
storybook addon-docs blocks
import React from 'react';
import { DocsContainer } from '@component-controls/storybook';
import { Story, Title, Playground } from '@component-controls/blocks';
const Page = ({ active }) => (
<DocsContainer active={active} >
<Title>Component controls blocks</Title>
<Playground openTab="source" title=".">
<Story id="." />
</Playground>
</DocsContainer>
);
const page = {
key: 'component-page',
title: 'Controls blocks',
render: ({ active }) => active ? <Page /> : null
}
export default page;
component-controls blocks
import React from 'react';
import { DocsContainer as SBDocsContainer, Preview, Story as SBStory, Title as SBTitle, Props} from '@storybook/addon-docs/blocks';
import { useContext } from '@component-controls/storybook-custom-docs';
import { DocsContainer } from '@component-controls/storybook';
import { Story, Title, Playground, PropsTable } from '@component-controls/blocks';
const Page = () => {
const context = useContext();
return (
<>
<h1>Mixing storybook docs blocks and component-controls blocks</h1>
<SBDocsContainer context={context}>
<SBTitle />
<Preview >
<SBStory id={context.storyId} />
</Preview>
<Props of='.' />
</SBDocsContainer>
<DocsContainer storyId={context.storyId}>
<Title />
<Playground openTab="source" title="." dark={true}>
<Story id="." />
</Playground>
<PropsTable of="." />
</DocsContainer>
</>
);
}
const page = {
key: 'mixed-page',
title: 'Mixed blocks',
render: ({ active }) => active ? <Page /> : null,
}
export default page;
Mixed addon-docs and component-controls

--

--

--

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

Difference Between JavaScript and TypeScript

Difference Between JavaScript and TypeScript

Blog post 402

Node.js Isn’t Always the Answer for Web Developers, No Matter What You Do

top view of many people sitting at a big desk with computers, phones, coffee, headphones, etc, working.

Herramientas Basicas DEFI

Here is why appendChild moves a DOM node between parents

Automate publishing npm packages

Why NVM is Tremendously Helpful for Web Developers

Learn Javascript with me!

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Atanas Stoyanov

Atanas Stoyanov

More from Medium

LinkedIn Clone

If you’re worried about Prop Drilling in React, try this.

React 18.0 has been released! I will try to summarize what’s new in one word: