Our front-end development at Bonusly focuses on building and maintaining React components. The React development experience is great and makes building an application intuitive. Yet, state and user permissions can be difficult to debug. We often need to manipulate the database to configure the application into the state we need. This process is brittle and relies on knowing what parts of the state need modification.

Enter Storybook

We’ve started using a component library to debug our components during development. Storybook is the clear choice due to its large feature set and helpful addons. We adopted it for the project and set out to find a development process to work with it.

“Storybook is an open source tool for developing UI components in isolation for React, Vue, Angular, and more. It makes building stunning UIs organized and efficient.”

Storybook builds from “stories” which encapsulate the rendered state of a component. You can write many stories for a component which reflect the many complicated variations of a component. You can think of stories like test cases in a test suite. Each one reflects an aspect of the application that we care about.

Storybook also provides controls for stories. These controls allow a user to view and set component props. Storybook can intuit the controls for a components based on Typescript type inference. Writing the component prop type definitions configures the controls for a component.

Beyond component documentation and a development playground, what other roles can Storybook fill?

What exactly is Storybook-Driven Development?

The basis of Storybook-Driven Development (SDD) is a well known software development philosophy: Test-Driven Development, known as TDD. TDD follows a process where developers write tests before the code they test. The code is then written and revised until the test written for the code succeeds.

In an SDD lifecycle the component stories take the place of tests. When tackling a new task, developers outline the stories first with expectations of what variations a component will need. They then fill out the prop values that make up the different component variations that occur in the application. Stories fail to match a visual design until a developer writes the code for the component.

import { Meta, Story } from '@storybook/react/types-6-0';
import { Button, Props } from '../../components/Feedback/Button';

export default {
  title: 'Elements/Button',
  component: Button 
} as Meta;

const Template: Story<Props> = (args) => <Button {...args} />;

export const Basic = Template.bind({});
Basic.args = {
  children: 'Submit',
};

export const Rounded = Template.bind({});
Rounded.args = {
  children: 'Create New Signal',
  rounded: true
};

export const Icon = Template.bind({});
Icon.arg = {
  children: 'Update Responses',
  imageUrl: 'https://signals-production-cdn.bonus.ly/static/media/caret_right.88a7008c.svg'
};

Storybook can also serve as a check for other key criteria of components. One addon we use to check for component completion is Storybook’s accessibility addon. It provides many inspections that provide feedback on a component’s accessibility.

Storybook a11y addon

Automating Storybook-Driven Development

The Storybook framework also can be a platform for automated testing. Storybook alleviates a lot of things that make behavior testing difficult. Configuring testing environments, coordinating services, providing test data, and authenticating headless test engines can be painful with traditional testing frameworks. Because stories use mocked data, tests against them can expect consistent results.

Client-driven GraphQL schemas

Our new platform makes heavy use of GraphQL queries and mutations. We use the Apollo Client library to make our requests to the GraphQL backend. Thanks to its hook-based API these requests have wound up throughout our application.

Luckily for us, there is an excellent Storybook addon which hooks into the Apollo Client library and passes along mock queries and mutations that we provide, enabling us to mostly disregard whether a component is focused on presentation or encapsulating application behavior.

Storybook Apollo Client addon

We can build our user interfaces first with the data shapes we will need. We then revise those shapes as we fill out the component, its variants, and its behavior. Finally, we build and resolve those schemas on the server when a component is complete. This process avoids issues caused by the lack of versioning in GraphQL schemas.

Lower barrier of entry

One of the killer features of Storybook is its simplicity and isolation. This enables team members to check code change with minimal environment setup.

The barrier to entry can be further lowered by building and deploying Storybook as a static website. Designers, product managers, and others can visit URLs to view isolated components. We’re hoping Storybook can create a more inclusive code review.

Beware of the pitfalls

Storybook-driven development isn’t a perfect software development philosophy. It only works if people or automations actually look at the stories. Storybook’s value diminishes if breaking changes make their way into the codebase. Buggy or broken output for a component makes it difficult to work with and provides no value.

Storybook-driven development also doesn’t account for the entire breadth of an application. The point of Storybook is to decouple components from other parts of the application. This decoupling can lead to inattention to how components integrate within the application. Storybook should not replace manual or automated end-to-end testing of the application.

Finally, stories need boilerplate and sometime verbose mock data. Storybook’s API has improved over the past few versions and reduced the boilerplate. The new inference of controls meant a reduction in the amount of boilerplate. Mocking data can be quite verbose but mocks can provide value beyond Storybook. Automated tests could use the same mocks used for stories.

Key takeaways

Storybook-driven development promotes a software development lifecycle with a low barrier of entry. It removes system concerns and focuses developer concerns on front-end problems. Stories can capture edge cases for easy access. Everyone can know that they’re looking at the same component state when they open up a story on a branch.

Storybook has had a big impact on how we develop code at Bonusly. We’re excited for new addons and features that will further refine our development process.