Fragmented Thought

Exposing custom controls using Storybook 7's new Meta type

By

Published:

Lance Gliser

Heads up! This content is more than six months old. Take some time to verify everything still works as expected.

By default, all stories using the Component Story Format sense and provide the component's details through props. Yet there's times when you need a way to customize a story doing something that isn't a part of the component itself. Most often this comes up when you're using the render method, and need to test out variants of a wrapping element.

In this example, we'll wrap an arbitrary Markdown component in MUI's cards and give a means of setting the card header and summary text to the controls.

import Markdown from "./Markdown"; import React from "react"; import { Card, CardHeader, CardContent, Typography } from "@mui/material"; const oneLoremIpsum = getLoremIpsumParagraphs(1); const title = oneLoremIpsum.split(" ").slice(0, 4).join(" "); const subtitle = oneLoremIpsum.split(" ").slice(0, 9).join(" "); // Create a type to declare our custom control additions: type ControlArgs = { title: string; subtitle: string; }; // We'll bypass the standard Meta type: // const meta: Meta<typeof Markdown> = { ... } // Instead using the types directly: const meta: ComponentAnnotations< ReactRenderer, ComponentProps<typeof Markdown> & ControlArgs > = { component: Markdown, // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/7.0/react/writing-docs/docs-page tags: ["autodocs"], parameters: { // More on Story layout: https://storybook.js.org/docs/react/configure/story-layout layout: "centered", }, // More on argTypes: https://storybook.js.org/docs/react/api/argtypes argTypes: {}, args: { // Include our custom args title, subtitle, // And args for the component content: ` # Heading 1 ${oneLoremIpsumParagraph} - ${oneLoremIpsumSentence} - ${oneLoremIpsumSentence} - ${oneLoremIpsumSentence} ![img](https://i0.wp.com/css-tricks.com/wp-content/uploads/2016/01/choose-markdown.jpg) [Learn markdown](https://www.markdownguide.org/) `.trim(), }, // Pull our custom args out for use, and continue to pass the rest along. render: ({ title, subtitle, ...args }) => ( <Card> <CardHeader title={title} /> <CardContent sx={{ width: "65em" }}> <Typography>{subtitle}</Typography> <Markdown {...args} /> </CardContent> </Card> ), }; export default meta; type Story = StoryObj<typeof meta>; // More on component templates: https://storybook.js.org/docs/react/writing-stories/introduction#using-args export const Primary: Story = { // More on args: https://storybook.js.org/docs/react/writing-stories/args args: {}, };