We're live-coding on Twitch! Join us!
Building a UI Component with React and Storybook

Building a UI Component with React and Storybook

Code Demo

In the previous article, I gave an Introduction to Storybook and how it can be used to organize and build JavaScript components. Storybook is a UI library that can be used to document components. In this article, I’ll be explaining how to build an interactive UI component using React and Storybook. We’ll be creating a UI component using Storybook and React and at the end of the tutorial, we’ll deploy the storybook as a stand-alone application to serve as a style guide.

TLDR

  • Create a React Project
  • Add storybook/react as a dependency
  • Create a UI component Library with Storybook
  • Customize themes
  • Deploy as a static site

Installation Guide

To get started we’ll need to create a new react project and for this, we’ll be using create-react-app which is a great tool for scaffolding react applications and then go ahead to install storybook.

// command to scaffold a react app
npx create-react-app storybook-app
cd storybook-app
yarn or npm start

And the next step will be to install the storybook package into our project.

// command to install storybook
npx -p @storybook/cli sb init

The command can automatically detect the framework we are using from the package.json file and install the storybook version of that framework. After running both commands simultaneously, we can confirm we have storybook-react dependencies installed by going over to the package.json file to see if the packages are installed and then we can go ahead and run the application as well as run storybook.

// start the app
yarn start
// run storybook command
yarn storybook

After running both commands, We’ll have both the react app and the storybook app running on different ports.

Essential Reading: Learn React from Scratch! (2019 Edition)

Adding Stories To React App

Now that we are done with the setup, we can go ahead and create components using Storybook. The idea here is to first setup storybook if we followed the steps outlined above, then it’s already preconfigured for us else if we installed the storybook/react package in an already existing react project then we’ll need to follow these steps to setup storybook. we’ll first want to create a folder .storybook in the root directory of our React project and then create a file within the folder called config.js file and add the following lines of code to the file.

import { configure } from '@storybook/react';
function loadStories() {
  require('../src/stories');
}
configure(loadStories, module);

The block of code above is a configuration for storybook and it tells Storybook to find the stories in the src/stories directory. We’ll go ahead and create that folder if we don’t have it already set up. Within the src folder create a folder called stories. This is where all the components we will create stories for will eventually be located. In this tutorial, I’ll be creating a Button component and for this component, we will document stories for them within the stories folder. I’ll go ahead and create a Button Component within the component directory with the following lines of code.

import React from 'react';
import './Button.css';
const Button = props => (
  <button onClick={props.onClick} style={props.style}>
    {props.label && <span>{props.label}</span>}
  </button>
)
export default Button;

Now, we can go ahead and add a story for the button component created. Within the stories directory create a file and call it buttonStories.js and then we’ll add the following lines of code into the file.

import React from 'react';
import { storiesOf } from '@storybook/react';

import Button from '../components/Button';

storiesOf('Button', module)
  .add('with primary', () => <Button label="Primary Button" />)
  .add('with outline', () => <Button
    label="Ouline Button"
    style={{ background: 'transparent', border: '3px solid #fecd43' }}
  />)
  .add('with rounder corners', () => <Button
    label="Rounded Button"
    style={{ borderRadius: '15px' }}
  />)
  .add('disabled', () => <Button disabled
    label="Disabled Button"
    style={{ background: 'gray' , border: 'gray', cursor: 'not-allowed' }}
  />)

Next, We’ll create an index.js file which will serve as a base file with all stories, then we can import all into this file. Go ahead and import the buttonStories.js file and then for every new file created under stories directory we will import them into this file.

import './buttonStories';

Integrating Addons

Addons with Storybook helps implement extra features to make them more useful and interactive. In this article, we will be adding the Action addon to the stories created. The Actions Addon can be used to display data received by event handlers in Storybook. A full list of all addons available with Storybook can be found here. We can go ahead and set up the addon if it’s not already done by default you will need to follow these steps. Install the addon package with this command.

npm i -D @storybook/addon-actions or yarn add @stroybook/addon-actions

Then, add the following content to .storybook/addons.js

import '@storybook/addon-actions/register';

To make our Button story interactive with Storybook we can add the following code to buttonStories.js

import React from 'react';
import { storiesOf } from '@storybook/react';
import { action } from '@storybook/addon-actions';

import Button from '../components/Button';

storiesOf('Button', module)
  .add('with primary', () => <Button
    onClick={action('click')}
    label="Primary Button"
  />)
  .add('with outline', () => <Button
    label="Ouline Button"
    onClick={action('click')}
    style={{ background: 'transparent', border: '3px solid #fecd43' }}
  />)
  .add('with rounder corners', () => <Button
    label="Rounded Button"
    onClick={action('click')}
    style={{ borderRadius: '15px' }}
  />)
  .add('disabled', () => <Button disabled
    label="Disabled Button"
    onClick={action('click')}
    style={{ background: 'gray' , border: 'gray', cursor: 'not-allowed' }}
  />)

There you have it. To see this in action when you run storybook, on the tab below you’ll see an Actions tab where the action is logged anytime we interact with the buttons.

Customizing Themes

With storybook, we have the ability to customize the default theme used and storybook comes bundled with a default light theme. Now let’s see how we can customize this to something different. Dark theme maybe or something entirely different. To get started we’ll need to modify the configurations we have set in config.js file by adding the following lines of code.

import { addParameters } from '@storybook/react';
import { themes } from '@storybook/theming'
addParameters({
  options: {
    theme: themes.dark
  }
})

With the dark theme configured, we can see the entire storybook theme look different and have switched to the dark theme. At any point, this can be switched back to either light or dark theme depending on our preference. We can also go ahead and define a dynamic theme out of the box if we want a different theme entirely. Let’s take a look at how we can achieve this. The first step is to create a file for our theme, within .storybook folder create a new file called yourTheme.js. I’ll be using pinkPanther as the name of our theme. Next step is to generate a new theme using the create() function from storybook/theming

import {create} from '@storybook/theming'
export default create ({
  base: 'light',
  colorPrimary: 'hotpink',
  colorSecondary: 'deepskyblue',
  // UI
  appBg: 'rgb(234, 0, 133)',
  appContentBg: 'white',
  appBorderColor: 'white',
  appBorderRadius: 4,
  // Typography
  fontBase: '"Open Sans", sans-serif',
  fontCode: 'monospace',
  // Text colors
  textColor: 'rgb(255, 250, 250)',
  textInverseColor: 'white',
  // Toolbar default and active colors
  barTextColor: 'white',
  barSelectedColor: 'white',
  barBg: 'rgb(246, 153, 190)',
  // Form colors
  inputBg: 'white',
  inputBorder: 'silver',
  inputTextColor: 'black',
  inputBorderRadius: 4,
  brandTitle: 'Pink Panther Storybook',
  brandUrl: 'https://example.com',
  brandImage: 'https://botw-pd.s3.amazonaws.com/styles/logo-thumbnail/s3/0019/2539/brand.gif?itok=97rSwE0a',
});

Then we can go ahead and import pinkPanther.js in our storybook config file.

import pinkPanther from  './pinkPanther';
addParameters({
  options: {
    theme: pinkPanther
  }
})

Pink Panther theme

This gives us a completely different theme as seen above. The possibilities with how we can customize our storybook is up to us and our design team if we want something fancy. I hope we can find my pink panther obsession helpful in this context.

Deploying Storybook

One feature that comes bundled with Storybook is the fact that we can deploy our storybook as a static site isolated on its own that we can deploy to either Netlify or any hosting option of our choice. To configure this we will need to add a build-storybook script to our package.json.

{
  "scripts": {
    "build-storybook": "build-storybook -c .storybook -o .out"
  }
}

What this script will do is that it’ll build our storybook directory into a static web app and output it in a .out directory. We can run this script and deploy the content of the .out directory when the build is complete. Go ahead and run the command.

yarn build-storybook

When the build is complete we can now deploy the content of the directory using any hosting of our choice. To test this works locally, we can run the following command and it’ll serve the content of the folder as a static site.

npx http-server .out

Wrapping Up

In this article, We’ve learned how to build interactive components using Storybook and React. Now we have seen what is possible with Storybook and also have a guide on how to integrate storybook as a component library in our react projects. Developing with Storybook serves as a single source of truth for both developers and designers working in a team and it can be integrated with other front end frameworks this post only outlines how it is used with React, In case you’re looking out for a guide on other frameworks feel free to check Storybook’s docs. You can also find the code for this article on GitHub.

Like this article? Follow @lauragift21 on Twitter