-
Notifications
You must be signed in to change notification settings - Fork 6
Anatomy of a Story
This for Storybook v8.x.
This is a deep dive into how we write and structure a story for a component. To find out more about a component, check out the Anatomy of a Component page.
When creating stories, we want to document as much as possible for the component itself and how to use the component with other DS components or other libraries. More is better. The goal for maintainers and contributors is to write consistent-looking stories and documentation that other developers can use to easily figure out how to implement a component or pattern in their project.
Currently, many stories are written using Markdown Documentation(MDX) and Controls to dynamically update a component's props.
When writing a story, two files must be created. The .mdx
file contains the Storybook documentation blocks and the .stories.tsx
file contains the React code including the DS component examples.
The following block format is the convention used for documenting DS components in the .mdx
file.
-
<Meta>
- Each file must contain this Storybook component and include an
of
prop to define the component it's documenting.
- Each file must contain this Storybook component and include an
- Title
- An h1
#
heading
- An h1
- Component Version Table
- This table contains the DS version where the component was first added and where it was last updated.
- Table of Contents
- List of all the headings in the component's story. This always includes
Overview
,Component Props
, andAccessibility
in that order as well asChangelog
as the last section. The rest of the headings are based on props that should be highlighted and examples.
- List of all the headings in the component's story. This always includes
- Overview
- This mandatory first heading contains the general description of the component.
- Declare
<Description of={...}>
to use the component's code comment block for its description.
- Component Props
- This mandatory heading contains the main
Canvas
block withof
set to controls in Storybook's "Canvas" section. - This section also declares
<ArgsTable of="...">
to display the comment block for every prop in the component’s interface.
- This mandatory heading contains the main
- Accessibility
- This mandatory heading contains accessibility information about the component.
- Make sure this also contains a list of "Resources" linking to relevant accessibility resources. Link credible resources such as from W3C or Deque.
- Optional Headings
- If additional headings were declared in the "Table of Contents", those headings must be written here. Typically, they describe component variants, component props, and component examples.
- Here's where the
<Canvas>
component and text can be used to render patterns and code blocks to resemble the component examples from the relevant Figma designs.
- Changelog
- This section renders the
ComponentChangelogTable
helper component to display a changelog table for the component.
- This section renders the
The following example is shortened for brevity. For more details, see the full Button.mdx
example.
Button.mdx
import { ArgTypes, Canvas, Description, Meta } from "@storybook/blocks";
import { changelogData } from "./buttonChangelogData";
import ComponentChangelogTable from "../../utils/ComponentChangelogTable";
import * as ButtonStories from "./Button.stories";
import Link from "../Link/Link";
<Meta of={ButtonStories} />
# Button
| Component Version | DS Version |
| ----------------- | ---------- |
| Added | `0.0.4` |
| Latest | `3.1.1` |
## Table of Contents
- {<Link href="#overview" target="_self">Overview</Link>}
- {<Link href="#component-props" target="_self">Component Props</Link>}
- {<Link href="#accessibility" target="_self">Accessibility</Link>}
- {<Link href="#button-groups" target="_self">Button Groups</Link>}
- {<Link href="#changelog" target="_self">Changelog</Link>}
## Overview
<Description of={ButtonStories} />
Update the `buttonType` in the Controls section to see the types of buttons
that can be rendered.
- `"primary"` is used for actions that move the user forward. This is the default.
- `"secondary"` is used for actions that move the user back, such as cancellations.
- `"text"` is used for equally weighted actions in a text based list.
// ...
## Component Props
<Canvas of={ButtonStories.WithControls} />
<ArgTypes of={ButtonStories.WithControls} />
## Accessibility
The Reservoir `Button` component renders an HTML `<button>` element that is
accessible.
// ...
Resources:
- [W3C WAI ARIA Button](https://www.w3.org/TR/wai-aria-practices-1.1/#button)
- [W3C WAI ARIA Button Examples](https://www.w3.org/TR/wai-aria-practices-1.1/examples/button/button.html)
## Button Groups
Primary and secondary buttons should be grouped like in the following example.
The `ButtonGroup` component should be used to wrap the `Button` component.
<Canvas of={ButtonStories.ButtonGroups} />
// ...
## Changelog
<ComponentChangelogTable changelogData={changelogData} />
The following is the convention used for creating DS components Stories in the .stories.tsx
file.
-
meta
object- This is typed using Storybook's
Meta
type with the component's type as input. - This contains
title
,component
, andargTypes
properties. - The
title
organizes the component in the desired category in the Storybook site's sidebar. - The
argTypes
varies per component and here is where we can control if a prop is enabled in the "Controls" section, how it should render, and what option values are available. - This must be the default export for Storybook to add to its site.
- This is typed using Storybook's
-
Story
type- This type is created based on Storybook's
StoryObj
type. This helps declare each component block when it's rendered on the page.
- This type is created based on Storybook's
-
WithControls
story- Our convention is to name the "main" story block
WithControls
. This is always the first story declared and exported after themeta
object. This sets theWith Controls
example as the first story in Storybook's sidebar component section. This is the dynamic story block that users can controls in Storybook.
- Our convention is to name the "main" story block
- Other Story examples
- Any additional stories can be created based on how the props or examples should be documented. For example, does a component have five variants? A single Story can be created that renders all five variants together. These examples are always static and we don't want users to change them so they are NOT connected to Storybook's "Controls".
The following example is shortened for brevity. For more details, see the full Button.stories.tsx
example.
import { Box, VStack } from "@chakra-ui/react";
import type { Meta, StoryObj } from "@storybook/react";
import Button from "../Button/Button";
import ButtonGroup, { buttonGroupWidthsArray } from "./ButtonGroup";
import Heading from "../Heading/Heading";
const meta: Meta<typeof ButtonGroup> = {
title: "Components/Form Elements/ButtonGroup",
component: ButtonGroup,
argTypes: {
buttonWidth: {
control: { type: "radio" },
options: buttonGroupWidthsArray,
table: { defaultValue: { summary: "default" } },
},
className: { control: false },
id: { control: false },
isDisabled: { table: { defaultValue: { summary: false } } },
layout: {
control: { type: "radio" },
options: ["column", "row"],
table: { defaultValue: { summary: "row" } },
},
},
};
export default meta;
type Story = StoryObj<typeof ButtonGroup>;
/**
* Main Story for the ButtonGroup component. This must contains the `args`
* and `parameters` properties in this object.
*/
export const WithControls: Story = {
args: {
buttonWidth: "default",
className: undefined,
id: "button-id",
isDisabled: false,
layout: "row",
},
parameters: {
jest: ["ButtonGroup.test.tsx"],
},
render: (args) => (
<ButtonGroup {...args}>
<Button buttonType="secondary" id="group-1">
Button
</Button>
<Button id="group-2">Submit</Button>
</ButtonGroup>
),
};
// The following are additional ButtonGroup example Stories.
export const Width: Story = {
render: () => (
<VStack align="left" spacing="l">
// ...
</VStack>
),
};
// ...
Still have questions? Want to improve this documentation? We're available on the #design-system slack channel.