developers

Setting Up a Component Library with React and Storybook

Learn how to set up a component library with React and Storybook to create modular and reusable components that can be shared across projects.

Sep 11, 201814 min read

Storybook is a development environment for UI components. It let us browse a component library, view the different states of its components, and interactively develop and test them. Storybook runs outside of our application; therefore, we can develop UI components in isolation without worrying about any project dependencies and requirements.

We've shared about our experience using React and Storybook to better manage components. In this post, we are going to explore how to organize a basic project, how to implement a style guide to help us achieve consistent branding, and how to build the foundation of a component library to make our components reusable and easy to maintain.

Let's start.

Setting Up a React Project

We are going to use

create-react-app
to scaffold easily a new React application.

We can run

create-react-app
using
npx
which comes bundled with
npm 5.2+
and higher:

npx create-react-app marvel-bank
cd marvel-bank

If you use

npm 5.1
or earlier, you can't use
npx
. Instead, install
create-react-app
globally:

npm install -g create-react-app

And then run:

create-react-app marvel-bank
cd marvel-bank

Notice that we are not running

npm start
. As mentioned earlier, we don't need to have a running React application to use Storybook.

Open the newly created

marvel-app
folder on your preferred code editor or IDE.

Within

marvel-bank
, the
src
folder contains the core business logic of our React application. Let's do some housekeeping and remove files and code that we don't need.

Open

src/App.js
and trim it like so:

// src/App.js

import React, { Component } from "react";
import "./App.css";

class App extends Component {
  render() {
    return <div className="App" />;
  }
}

export default App;

Next, let's delete the following files:

  • App.test.js
  • logo.svg

Spoiler: Storybook is an essential part of our testing stack as it makes testing a painless experience.

Using a Style Guide for Consistent Branding

Using a style guide can lead to better application design and development. As explained by the Marvel Design team, "during the design phase style guides encourage consistency in the visual identity and help keep the interface system as logical as possible, which makes for a better UX."

What is a style guide anyway? Marvel has a solid answer: "A style guide clearly demonstrates how all interface elements and components are to be visually represented. It’s essentially a master reference for the user interface (UI)."

In this sense, a component library is part of a style guide as it presents our components visually and it is the single source of truth for each component (the master reference). To create a comprehensive style guide, the component library can be accompanied by design documents that define font styles and sizes as well as primary and secondary user interface colors. A Design Team usually creates a "UI Kit" that is handed to developers for implementation. Shopify explains that a UI kit is an assortment of graphic files that include UI components (buttons, checkboxes, progress bars, etc.) for the purpose of defining and designing the user interface.

A component library helps you achieve consistent branding as it becomes the single source of truth for every component not only in the application but for all projects in the organization

Tweet This

For the online banking app that we are going to start creating in this blog post, we are going to use a free Banking UI Kit that Marvel created for Sketch. To honor their effort, we named the app

marvel-bank
. The UI Kit looks as follows:

Marvel Banking UI Kit

The UI Kit is designed for iOS, but we are going to adapt it for usage in a responsive web application. To make it easier for developers to understand the UI Kit, I created a design document where we can get the font names, the sizing, the color hex codes, etc: Marvel Bank Style Guide.

In the following excerpt, notice how is much easier to understand the guidelines that a developer would need to follow when creating the components presented in the UI Kit:

Style guide design - typography and color palette

If we need to implement a green button, we can consult the design document and copy the hex code of

$green
; however, it would be much easier if we could code the elements of the design document into our application in a modular way and reusable way. We have plenty of options to do that:

Our Team currently has been using a combination of Stylus and CSS Modules to manage the styling of the projects. React has unified the three layers of front-end development (HTML, CSS, and JavaScript) under one layer powered by JavaScript, JSX, and CSS-in-JS. For this post, however, we are going to rely on SCSS to create the modular components to minimize the development overhead.

Feedback: Would you like to learn how we are using

styled-components
to create a modern component library? Let us know in the comments below and we could create a blog post about it.

Adding SCSS to
create-react-app

We can add

SCSS
support to
create-react-app
without having to
eject
to a custom setup. We need to install a few packages to help us achieve that goal:

NPM:

npm install --save node-sass-chokidar npm-run-all

node-sass-chokidar
is a thin wrapper around the node-sass executable to use chokidar instead of Gaze when watching files.

npm-run-all
is a CLI tool to run multiple npm-scripts in parallel or sequentially.

Next, we need to modify our

package.json
"scripts"
property to watch and process
.scss
files into
.css
ones:

{
  "name": "marvel-bank",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "node-sass-chokidar": "^1.3.3",
    "npm-run-all": "^4.1.3",
    "react": "^16.4.1",
    "react-dom": "^16.4.1",
    "react-scripts": "1.1.4"
  },
  "scripts": {
    "build-css": "node-sass-chokidar src/ -o src/",
    "watch-css":
      "npm run build-css && node-sass-chokidar src/ -o src/ --watch --recursive",
    "start-react": "react-scripts start",
    "start": "npm-run-all -p watch-css start-react",
    "build-react": "react-scripts build",
    "build": "npm-run-all -s build-css build-react",
    "test": "react-scripts test --env=jsdom",
    "eject": "react-scripts eject"
  }
}

These scripts allow us to compile

.scss
files into
.css
and to keep watching the
src
folder for changes to the content of existing
.scss
files or the addition of new ones. To complete this task, we need to change the file extension of
App.css
and
index.css
to
.scss
. Depending on our development environment, this can be done in different ways such as renaming the files or refactoring their name or file type.

Storybook will only understand changes made or applied in

.css
files. If we were to make a change in a
.scss
file, we would need to compile it into
.css
for Storybook to be notified of the styling changes.

Normally, such compilation is a build step in our development workflow triggered by running

npm start
. However, I made the promise that we wouldn't have to run our React app in order to use Storybook in this blog post. I am keeping that promise and
npm start
is off-limits. What can we use instead?
watch-css
.

As stated earlier,

watch-css
compiles our SCSS into CSS files using the
build-css
script and it keeps monitoring all the SCSS files present under the
src
directory to detect any changes. Anytime an SCSS file is changed, that file is compiled and Storybook is able to see and apply the styling changes into the component preview (as we'll see soon!).

With this in mind, on the shell run the following command:

npm run watch-css

This is a good point to make our first

git
commit.

Using
git
Version Control

Our project is in a good place for its first

git
commit. But before we do so, let's ensure that we have everything we need to ignore specified in the
.gitignore
file. If you are using an IDE like WebStorm, for example, there are extra files that the IDE creates that is better to keep out of the
git
repo.

I personally like to use

gitignore.io
to generate the content of my
.gitignore
file automatically. The categories that I choose to create the file are WebStorm, IntelliJ, OSX, Windows, and Visual Studio Code, since they are the tools and platforms that are most commonly used. You may head to that site, enter those categories, and copy/paste the output at the end of the
.gitignore
file present in our project.

Since our

.css
files are built automatically under our project configuration, we do not need to include them in version control. In the
.gitignore
file add the following rule at the end:

// .gitignore

// ...

src/**/*.css

This rule ensures that none of the

.css
files under the
src
folder are tracked by
git
.

With a comprehensive

.gitignore
file in place, let's initialize a
git
repository (make sure that
marvel-app
directory is the current working directory):

git init

Let's run a quick

git status
check to see what files are being untracked:

git status

Let's go ahead and add these files shown to

git
in order to include them in our commit:

git add .

We used a shortcut here to add all the files that were being untracked using the

.
after the
add
command.

If you want a

git
refresher, I highly recommend this amazing Git & Version Control tutorial by the folks at Git Tower.

Running

git status
again would show us the new files that have been added that include changes to be committed. Let's create our first commit then:

git commit -m "Initial commit"

We'll get a reply by

git
showing all the files that were changed and the insertions that were made. Having a well-thought commit history in place will let us go back in time if we ever need to use an older version of our code.
CTRL/CMD + Z
can only go so far back!

This all looks good to me (LGTM™), but before we include any styling or components in our project, we need to create a sound file structure.

Project Structure

An internal pattern that we use is to have specialized folders to hold the different elements of our React application. In one of our projects, we have the following structure:

- src
    |-- api/
    |-- features/
    |-- assets/
    |-- redux/
    |-- styles/
    |-- utils/
    |-- App.js
    |-- index.js
    |-- routes.js

For the initial phase of this project, we only need the

features
and the
styles
folder. The
features
folder holds our components in a categorized manner. We define features of our applications, such as
search
or
reports
in its subfolders, and create components that power and build that feature. What Storybook will help us solve is the event where features share components. Instead of duplicating the code across features, the feature will implement the component from a central source: our component library. As the name suggests, these common components go into a
common
feature folder.

This is the project structure we want for the

src
folder in this phase of the project:

- src
    |-- features/
    |---- common/
    |-- styles/
    |---- _theme.scss
    |-- App.js
    |-- App.scss
    |-- index.js
    |-- index.scss
    |-- registerServiceWorker.js

Instead of duplicating the component code across features in your project, implement the component from a central source, like a component library.

Tweet This

Let's go ahead and create these folders and files:

Demo banking app file and code structure

We'll be using

_theme.scss
in a moment. This is a good checkpoint. Let's go ahead and commit:

git status
git add .
git commit -m "Create project structure that integrates with SCSS"

Noticed something different this time? Since the

features
folder and its
common
subfolder are currently empty, they were not included as part of the commit bundle by git. We could place an
index.js
file inside
common
that exports all of the components within that folder using what is known as a barrel export. For this blog post, we are not going to use that just yet.

Creating the Application Theme

_theme.scss
is an SCSS partial that will be imported by any other component stylesheet that needs to apply the defined theme based on the Marvel Banking Style Guide. You can copy and paste the following definitions to your local
_theme.scss
file:

// src/styles/_theme.scss

// Fonts
$primary-font: "Lato", sans-serif;
$secondary-font: "Open Sans", sans-serif;

// Font Colors
$color-text: #4f6c8d;
$color-text-light: #a3adb4;
$color-text-lighter: #ccd6e1;

$color-text-contrast: #ffffff;
$color-text-contrast-light: #a7b5c6;
$color-text-contrast-lighter: #5f5f63;

// Background Colors
$gray: #bec9d1;

// Primary Colors
$blue: #506e8d;
$white: #ffffff;
$green: #6bbfab;
$red: #f96b6b;

// Dark Primary Colors
$dark-blue: #33475c;
$dark-white: #f0f0f0;
$dark-green: #5ba392;
$dark-red: #de5e5e;

// Auxiliary Colors
$bright-blue: #5db8eb;
$opaque-blue: #4770d6;
$opaque-yellow: #f3c416;
$opaque-red: #dd765f;

Since this is a significant checkpoint, let's commit again:

git status
git add .
git commit -m "Create app theme variables"

It's time to start creating components!

Creating A Reusable Button Using React

To see the benefits and value that Storybook provides us, we need to have components to visualize. Right now, we have none.

Recall that the Marvel UI Kit offers us the definition of a button that has three presentations:

Styling UI buttons - Primary, secondary, tertiary - Active and Disabled state buttons

These presentations can be summarized as follows:

  • Active State (Fill): The button is green, pops up, and has white text.
  • Active State (No-Fill): The button shares the background of the parent container, and it has a blue color for its text and border.
  • Disabled State: The button looks suppressed and has a light blue color for its text and border.

The button itself has two status: active or disabled. The relationship between presentation and state is something that we can express easily with Storybook. First, we need to plan the component. How are we going to approach its engineering?

Let's start with creating the basic structure of the component: a rounded rectangle that contains a label. Create a file named

Button.js
under the
common
folder and populate it with this:

// src/features/common/Button.js

import React from "react";

const Button = props => <div>{props.label}</div>;

export default Button;

Let's quickly commit the creation of the

Button
component:

git status
git add .
git commit -m "Create Button component"

Now that we have a component, we go back to one of the questions that we have been asking ourselves in our team when creating components:

  • How should a prototype of the component be presented? Should a blank page with mock data be used?

Traditionally, we would compose the component into a visible element of the UI to preview it. This time, we are going to use Storybook.

Next Steps

We have built a foundation to help us create our online banking web app with consistent branding by implementing a style guide. At Auth0, different teams are making extensive use of Storybook as a development and design tool. We are converging designers and developers into a Design Systems team that is letting us iterate faster and develop better products for our cherished customers.

Feel free to grab the source code of the project we have created so far from the Marvel Bank App GitHub repo. The repo is being built gradually and contains commits that cover the work we have done in this blog post and on future posts. To start from scratch, be sure to create a branch from the first commit:

Initial commit
.

For more content like this, follow @auth0 on Twitter or subscribe to our newsletter.

About Auth0

Auth0 by Okta takes a modern approach to customer identity and enables organizations to provide secure access to any application, for any user. Auth0 is a highly customizable platform that is as simple as development teams want, and as flexible as they need. Safeguarding billions of login transactions each month, Auth0 delivers convenience, privacy, and security so customers can focus on innovation. For more information, visit https://auth0.com.