Storybook Curation Guide - acl-services/paprika GitHub Wiki

  1. Component Stories
  2. Component Categories
  3. File System
  4. Common Helpers
  5. Good Examples

Component Stories

There is an established pattern now for component stories, with the goal of making it easier for the audience to learn where to find the information they are most interested in. The first level of stories under each component should include a limited number of consistent items to avoid being overwhelming.

  • Docs page

    • There should always be a Docs page and it should always be first
    • It should start with the imported content from the README.md
    • It should then describe the basic usage of the component by telling a "story"
    • It should embed concrete code examples by taking advantage of the MDX format
    • The storybook <Canvas isExpanded> component can be used if possible, if state or other hooks are not needed
    • These examples should clearly explain the most commonly used props and use cases
    • More complicated examples should be saved for more complex "Examples" stories
  • Showcase story

    • There should usually be a Showcase story following the Docs page
    • It should include the Storybook knobs decorator (or possibly controls in the future)
      • Most props should be added as knobs – for some props it may make more sense to use a select knob with predefined options that demonstrate common use cases
      • In some cases, children can be connected to a select knob, again to demonstrate common usage patterns
      • Props should not be included in the knobs if it doesn't help the audience to understand how to use the component
    • It should include the <CodeViewer> Paprika storybook helper component
  • Variations story

    • There should often be a Variations story that will display different visual permutations of the component at a glance
    • It may compose other "Examples" stories if it makes maintenance simpler
    • If it does not use composition it may utilize the <ExampleStory> helper to include a "Source" link in the header
    • It may be useful to reuse this story in Backyard/Tests/Screener for regression coverage with Screener
  • Examples stories

    • There should usually be some Examples stories that can demonstrate more complex use cases than in the README or Docs page
    • They may also be used to illustrate best practices and offer helpful "recipes"
    • Each Example story should always be isolated in its own js file, in the /stories/Examples folder
    • Each Example story should contain all code needed to understand the example – if code is shared between Examples, it's usually best to include a copy in each unless that distracts the reader from the purpose of the example
    • They should always use the <ExampleStory> helper:
      • Not in the individual js files, but in *.examples.stories.js
      • With component and fileName props required to include a "source" link to the GitHub source in the header
    • They should use <StoryHeading> and common.styles helpers where appropriate
    • Each component will need a different collection of Examples to tell its story – there is room for creativity and experimentation when writing Example stories, but, in general, it's best to keep it simple
  • Backyard

    • The Backyard folder is a catch-all for stories that the typical audience should not care about.
    • May include:
      • Cypress test stories
      • Screener test stories
      • Manual test stories
      • Edge cases
      • Development sandbox
      • Stories specifically for the Starling Design System site
    • Cypress tests should ONLY use test stories and utilize permalinks (with an id attribute attached to the default export in *.tests.stories.js.

Component Categories

The information architecture of the main Storybook navigation includes categories for all components. This is specified in /.storybook/storyTree.js and new components need to be added to the storyTree data structure in that file.

In stories this can be used something like this:

import { getStoryName } from "storybook/storyTree";
const storyName = getStoryName("Popover");

And in cypress tests like this:

import { getStoryUrlPrefix } from "storybook/storyTree";
cy.visitStorybook(`${getStoryUrlPrefix("Popover")}--showcase`);

File System

Each "folder" in the main Storybook navigation is represented by a single .stories.js file in the component's /stories directory. This is an unfortunate limitation of the Storybook CSF type stories.

By default, the stories will be added automatically in alphabetic order, but because there is a deliberate order we want to maintain for the first level of component stories, the main config file will attempt to load each component's .stories.js files in that prescribed order – but this relies on strict naming conventions.

  • MyComponent.stories.mdx
    • Docs page
  • MyComponent.stories.js
    • Showcase
    • Variations
  • MyComponent.examples.stories.js
    • All Examples stories
  • MyComponent.tests.stories.js
    • Test stories – usually Screener and sometimes Cypress
    • Should always be included in the Backyard folder via default export:
      export default { title: '${storyName}/Backyard/Tests' }

Additional .stories.js files can also be added and their stories will be included, alphabetically, after the stories in the above files.

Each story should be in its own individual file, in the /stories/Examples directory. Showcase, Variations, test stories, etc, can all go in that same Examples directory.

Common code

Since extracting shared code from a story can make it harder for the reader to quickly understand an example, it's usually best to copy/paste shared code in Storybook stories, but in some cases the shared code does not help explain the example and just adds clutter making it harder to focus on the important details. In these cases, it's reasonable to put this code in a separate file that can be imported by several stories.

Most of the time it's styling that is not important to the example and is useful to extract to a MyComponent.stories.stylers.js file, like for the Button. When it's not styling, the code can be kept in MyComponent.stories.helpers.js, like the Sortable.


Common Helpers

Story Parameters
storyParameters.js source ↗️

  • Using these shared story parameters allows consistent presentation of the storybook UI, like ensuring the addons panel is open when it is useful and closed when it is just in the way.
  • There are named exports for various "types" of story – these may be extended after importing to customize in specific instances (sometimes moving the addon panel from the right to the bottom makes more sense, depending on the component being showcased.
    • storyParameters
    • docsStoryParameters
    • showcaseStoryParameters
    • variationsStoryParameters
    • exampleStoryParameters
    • testStoryParameters

Styling Helpers
common.styles.js source ↗️

  • This file exports a number of styled-components and functions that help limit the styling choices story authors need to make:
    • <Story>
    • <CenteredStory>
    • <Rule>
    • <Big>
    • <Small>
    • <Tagline>
    • <Gap> / <Gap.Large> / <Gap.Small> / <Gap.Inline>
    • repeat(num, fn)
    • breaklines(num)

Helper Components
components/ source ↗️

  • The difference between the styling components and these is a bit arbitrary, but in general these components are a bit more sophisticated. They have props to make them more versatile instead of just some CSS encapsulated in a styled-component.
    • <CodeViewer> – An inline, collapsible source code viewer for Showcase stories
    • <ExampleStory> – A story wrapper to be used in index *.stories.js files that can include a tagline and a GitHub source link in the header
    • <Resizer> – A container with a draggable handle to illsutrate how a component responds to different container sizes
    • <StoryHeading> – A wrapper for the Paprika <Header> with limited levels (3) and some custom styling
    • <Blocks> – New!

Good Examples

The following can serve as a reference when creating new stories.

There's a good chance this list is already out of date, but was current as of Jan 14, 2021.

Simple components

More complex components

Unique components

⚠️ **GitHub.com Fallback** ⚠️