Back to blog

Component Story Format

Simple, portable, future-proof component examples

loading
Michael Shilman
โ€” @mshilman
Last updated:

Storybook is the worldโ€™s most popular UI component workshop. It enables structured UI development and testing for every major view layer including React, Vue, Angular, and many more.

Storybook 5.2 introduces Component Story Format (CSF), a new way to author stories based on ES6 modules. Component Stories are simple, easy to read, and decoupled from Storybookโ€™s internal API so you can use them anywhere.

Read on to learn more:

  • ๐Ÿ† Why: The big opportunity
  • ๐Ÿ“„ Format: What it is & why itโ€™s better
  • ๐Ÿšš Portability: Jest embedding example
  • ๐Ÿ”€ Codemods: How we make it easy to upgrade
  • โšก 3 minute install: Get started today
  • ๐Ÿ”ญ Whatโ€™s next?: The way forward

๐Ÿ† Why a new format?

Imagine if developing a component in Storybook automatically unlocked the ability to test it with Jest, import it in Sketch designs, paste it into InVision prototypes, and visually test it in Chromatic. What if your component library was universally accessible inside all your favorite tools?

In the last three years, components have risen to dominate the UI landscape. Everywhere you look there are new component-oriented tools for development, testing, design, and prototyping.

These tools engage in the creation and consumption of components and component examples (a.k.a. stories). But each tool has its own proprietary format because a simple, platform-agnostic way to express component examples doesnโ€™t yet exist.

The โ€œStoryโ€ is the source of truth for a component example

Storybookโ€™s popularity stems from its extensive, open source tooling for component development, testing, and documentation. These rich features make it essential to the frontend workflows of powerhouses like Airbnb, Slack, Squarespace, Lyft, Uber, and Dropbox.

However, if you peel everything away, Storybook is built on one core construct: the story.

A story is a code snippet that renders an example of a component in a specific state.

A story uses the production code shipped to users, which makes it the most accurate representation of a component example. Whatโ€™s more, stories are expressed in the view layer you use to build your app.

Tom Coleman, Norbert de Langen, and I originally set out to simplify writing stories in Storybook. Along the way we realized that creating an expressive, platform-agnostic format would allow developers to use stories in other tools and even independently of Storybook itself. This could improve the experience of everyone using components!

๐Ÿ“„ Component Story Format

Iโ€™m excited to introduce Component Story Format. If youโ€™ve used earlier versions of Storybook, youโ€™re probably familiar with the โ€œclassicโ€ storiesOf API:

storiesOf('atoms/Button', module)
  .add('text', () => <Button>Hello</Button>)
  .add('emoji', () => <Button>๐Ÿ˜€๐Ÿ˜Ž๐Ÿ‘๐Ÿ’ฏ</Button>);

This tried and true API gets the job done. But after helping tens of thousands of developers capture, document, and test key component states, weโ€™ve come up with a much better way:

export default { title: 'atoms/Button' };

export const text = () => <Button>Hello</Button>;
export const emoji = () => <Button>๐Ÿ˜€๐Ÿ˜Ž๐Ÿ‘๐Ÿ’ฏ</Button>;

CSF has every affordance of the storiesOf API, but brings many additional benefits:

๐Ÿ’Ž Simple. Writing stories is as easy as exporting ES6 functions from your story file in a clean, standard format you know and love.

๐Ÿšš Portable. Component stories are easily consumed anywhere ES6 modules live, including your favorite testing tools like Jest and Cypress.

๐Ÿ”ฅ Optimized. Component stories donโ€™t need any libraries other than your components. And because theyโ€™re ES6 modules, theyโ€™re even tree-shakeable!

โ˜๏ธ Declarative. The declarative syntax is isomorphic to higher-level formats like MDX, enabling clean, verifiable transformations.

๐Ÿ‘พ Future-proof. Component stories hide Storybookโ€™s underlying API, giving maintainers flexibility to improve Storybook without breaking any contracts.

๐Ÿšš Story portability

Component stories have no dependence on Storybook, so consuming them is as easy as importing an ES6 module. Consider how we might test interactivity with Jest and react-testing-library.

Hereโ€™s a CSF file for a stateful Counter component that increments its count on each click:

export default { title: 'Counter' };

export const enabled = () => (
  <Counter text="Enabled" />
);

export const disabled = () => (
  <Counter disabled text="Disabled" />
);

And hereโ€™s how we can use it in an interactive test:

import { render, fireEvent } from '@testing-library/react';
import { enabled, disabled } from './Button.stories';

describe('counter interactivity', () => {

  it('should increment when enabled', () => {
    const comp = render(enabled());
    fireEvent.click(comp.getByText('Enabled: 0'));
    expect(comp.getByText('Enabled: 1')).toBeTruthy();
  });
  
  it('should do nothing when disabled', () => {
    const comp = render(enabled());
    fireEvent.click(comp.getByText('Disabled: 0'));
    expect(comp.getByText('Disabled: 0')).toBeTruthy();
  });
  
});

With Component Story Format, this integration is simple and natural. Achieving the same result using storiesOf would require a significant restructuring of your code.

๐Ÿ”€ Convenient code migrations

What about your existing library of stories? Have no fear. With our entire existing user base depending on Storybookโ€™s classic API, weโ€™ll continue to support storiesOf for the foreseeable future.

That said, we want you to upgrade so weโ€™ve made it incredibly easy. Since everything in the storiesOf API has a direct equivalent in the Component Story Format, you can automatically migrate your existing stories in seconds.

For example, if you suffix your stories with .stories.js, converting your stories is as simple as running the following command in the Storybook CLI:

npx sb migrate storiesof-to-csf --glob "**/*.stories.js"

Storybook uses the amazing JSCodeshift under the hood to make this conversion fast and easy. Youโ€™ll also need to modify your call to configure if youโ€™re migrating from the storiesOf API.

โšก 3 minute install

Try out Component Story Format today in Storybook 5.2:

npx npm-check-updates '/storybook/' -u && npm install

To load Component Stories, Storybookโ€™s configure API gets a little facelift. Hereโ€™s a sample.storybook/config.js:

import { configure } from โ€˜@storybook/reactโ€™;

configure(require.context(โ€˜../src/โ€™, true, /\.stories\.js$/), module);

Finally, you can add a new story to verify itโ€™s working, and then run the automated migration (see above) on your story library. The migration overwrites your files so make sure your stories are in version control.

Or if you want to try it in a fresh project, Storybookโ€™s default setup now ships with Component Stories as default:

cd my-react-vue-angular-project
npx -p @storybook/cli@next sb init

And Bobโ€™s your uncle! ๐ŸŽ‰

๐Ÿ”ญ Whatโ€™s next?

Component Story Format is a foundational step forward for Storybook that brings immediate benefits including simplicity, portability, and optimizability.

The formatโ€™s long-term benefits will be even greater. An open, portable, and standards-based format enables the entire ecosystem of component design and dev tools to work together on behalf of users.

As the most popular component explorer, Storybook is well-positioned to promote a universal standard. More than 20,000 GitHub repos depend on Storybook (that we know of), with usage across every major front-end view layer by the largest companies in the world. Itโ€™s installed over 4M times per month on NPM.

Storybook users are already transitioning to CSF so that they can reuse their existing stories outside of Storybook in other tools and libraries.

๐Ÿ“ฃ Follow us on Medium or Twitter to see how the project evolves.

๐Ÿ’Œ If youโ€™re creating a tool that can benefit from CSF or any kind of Storybook integration, weโ€™d love to collaborate. Contact me: michael@hichroma.com.

Thanks to the community

Component Story Format was developed by Tom Coleman, Norbert de Langen, and Michael Shilman (me!), with testing and feedback from the entire Storybook community.

Storybook is the product of over 700 community committers and is organized by a steering committee of top maintainers. Thanks also to gracious donations on Open Collective.

If Storybook makes your UI development workflow easier, help Storybook get better. You can contribute a new feature, fix a bug, or improve the docs. Join us on Discord, support us on Open Collective, or just jump in on Github.

Join the Storybook mailing list

Get the latest news, updates and releases

6,615 developers and counting

Weโ€™re hiring!

Join the team behind Storybook and Chromatic. Build tools that are used in production by 100s of thousands of developers. Remote-first.

View jobs

Popular posts

Storybook DocsPage

Beautiful documentation, instantly
loading
Michael Shilman

Storybook 5.2

World-class design systems infrastructure
loading
Michael Shilman

Storybook 5.1

React Native โ€ข Accessibility โ€ข Context โ€ข Presets โ€ข Docs update
loading
Michael Shilman
Join the community
6,615 developers and counting
WhyWhy StorybookComponent-driven UI
DocsGuidesTutorialsChangelogTelemetry
CommunityAddonsGet involvedBlog
ShowcaseExploreProjectsComponent glossary
Open source software
Storybook

Maintained by
Chromatic
Special thanks to Netlify and CircleCI