Describe the bug
I have been writing stories using CSF, and the auto generated docs show the source code of the stories, as expected.
I'm using Storybook to build a sort of living design reference, so I wanted to add a status badge to each docspage indicating the readiness of each component. After much searching, I settled on the best way to achieve this being configuring parameters.docs.page and adding the badge component at the top. To save having to write this in every file, I made a helper function:
export const ComponentStory = (options: Options) => ({
title: options.title,
component: options.component,
parameters: {
docs: {
page: () => (
<>
<StatusBadge status={options.componentStatus} />
<DocBlocks.Title />
<DocBlocks.Subtitle />
<DocBlocks.Description />
<DocBlocks.Primary />
<DocBlocks.Props />
<DocBlocks.Stories />
</>
),
},
},
})
which is used like this:
export default ComponentStory({
title: "Components/Brand/CircleIcon",
component: CircleIcon,
componentStatus: "review",
});
However, this causes the story previews to show "no code available".

To debug a bit I tried writing it without the helper function:
export default {
title: "Components/Brand/CircleIcon",
component: CircleIcon,
parameters: {
docs: {
page: () => (
<>
<StatusBadge status="review" />
<DocBlocks.Title />
<DocBlocks.Subtitle />
<DocBlocks.Description />
<DocBlocks.Primary />
<DocBlocks.Props />
<DocBlocks.Stories />
</>
),
},
},
};
The code preview now works as expected.

I suspect this is because something in the chain doesn't recognise the function call version as being CSF.
To Reproduce
Steps to reproduce the behavior:
Expected behavior
The code preview on the generated docs page shows the source code for the story.
Screenshots/ Code
See above
System:
Please paste the results of npx -p @storybook/cli@next sb info here.
Environment Info:
System:
OS: Linux 4.19 Ubuntu 18.04.2 LTS (Bionic Beaver)
CPU: (4) x64 Intel(R) Core(TM) i5-4570 CPU @ 3.20GHz
Binaries:
Node: 12.16.3 - ~/.nodenv/versions/12.16.3/bin/node
Yarn: 1.22.0 - /mnt/c/Program Files (x86)/Yarn/bin/yarn
npm: 6.14.4 - ~/.nodenv/versions/12.16.3/bin/npm
Additional context
If there's an alternative more standard way to achieve what I want to do then I'm all ears. It seems a bit of a hassle to override the layout, when what I want feels more like a decorator for a story. I'm not sure that docs supports decorators, though.
Yes, CSF default exports should be plain objects. You can see more discussion here: https://github.com/storybookjs/storybook/pull/10959#pullrequestreview-431120762
Thanks @shilman. Would you be able to suggest an alternative way of adding a component to every docs page? Ideally I'd like to add one component without altering the default page order. Is there such a thing as decorators for docspages?
Yes there's a wrapper for the docs page: https://github.com/storybookjs/storybook/blob/next/addons/docs/docs/recipes.md#overwriting-docs-container
I would probably use story parameters:
export default {
title: 'blah',
parameters: {
componentStatus: 'deprecated'
}
}
...
Then define a new DocBlock and add it globally in .storybook/main.js (untested):
import React, { FC, useContext } from 'react';
import { DocsContext } from '@storybook/addon-docs/blocks';
const StatusBadge: FC<{}> = () => {
const { parameters: { componentStatus = 'unknown' } } = useContext(DocsContext);
return <>{componentStatus}</>;
};
import { StatusBadge } from '
export const parameters = {
docs: {
page: () => (
<>
<StatusBadge />
<DocBlocks.Title />
<DocBlocks.Subtitle />
<DocBlocks.Description />
<DocBlocks.Primary />
<DocBlocks.Props />
<DocBlocks.Stories />
</>
),
},
},
};
cc @domyen WDYT about building something like this in?
I support a feature that allows you to set componentStatus and get a badge. Most professional design systems have this pattern.
Loop me in :)
Thanks @shilman, the thought of default parameters didn't cross my mind but it makes total sense.
I instead found out that docs page decorators _do_ exist, and created one that parses a tag out of the component's JSDoc. e.g. @status stable
/**
* Decorator to display a component's status in its docspage.
*/
export default addParameters({
docs: {
page: (props: DocsPageProps) => {
const context = useContext(DocsContext);
// Ideally parsing the status could be done when the babel loader
// initally generates __docgenInfo
let status = context.parameters.component.__docgenInfo.status as ComponentStatus;
if (!context.parameters.component.__docgenInfo.status) {
const description: string = context.parameters.component.__docgenInfo.description ?? "";
const statusMatch = description.match(/@status\s+(.*)/);
status = (statusMatch?.[1] ?? "") as ComponentStatus;
context.parameters.component.__docgenInfo.description = description.replace(statusMatch?.[0]!, `\nComponent status: ${status}`)
context.parameters.component.__docgenInfo.status = status;
}
return (
<>
<StatusBadge status={status} />
<DocsPage {...props} />
</>
);
},
},
});
I'm sure it could be made more robust by customising the docgen step to parse the description further, but I'm happy something is working for now :)
@rikkit Fixed a typo in my code above default => const