Storybook is a user interface (UI) library that can be used to document components.
Note: This article builds upon Introduction to Storybook which covers how it can be used to organize and build JavaScript components.
In this article, you will build an interactive UI component using React and Storybook.
At the end of the tutorial, you will deploy the storybook as a stand-alone application to serve as a style guide.
To complete this tutorial, you will need:
This tutorial was verified with Node v14.4.0, npm
v6.14.5, react
v16.13.1, and @storybook/react
v5.3.19.
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.
- npx create-react-app storybook-app
Then navigate to the newly created project directory:
cd storybook-app
And the next step will be to install the storybook
package into our project:
- 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, we can confirm we have @storybook/react
dependencies installed by opening the package.json
file to verify if the packages are installed and then we can run the application as well as run Storybook.
- npm start
- npm run storybook
After running both commands, we’ll have both the React app and the Storybook app running on different ports.
If we followed the steps outlined above, then it’s already preconfigured for us. If we installed the @storybook/react
package in an already existing React project then we’ll need to follow these steps to set up 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
and add the following lines of code:
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 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.
Note: Storybook 5.3.0 and later introduce main.js
which handles what config.js
did in the past. The changes are documented in the official migration documentation.
If you are using Storybook 5.3.0 or later, you do not need a config.js
file and can ignore this step.
The official documentation also suggests different approaches for where to place stories
.
At this point, Storybook is set up for use.
Now that we are done with the setup, we can create components using Storybook.
In this tutorial, we’ll be creating a <Button>
component and for this component, we will document stories for them within the stories
folder. 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;
And add styles for the component:
button {
padding: 20px;
width: 20em;
margin: 10px;
color: white;
font-size: 19px;
cursor: pointer;
border: 2px solid #fecd43;
background: #fecd43;
}
Now, we can add a story for the <Button>
component created. Within the stories
directory create a file and call it buttonStories.js
and then 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, create an index.js
file. Import the buttonStories.js
file:
import './buttonStories';
This will serve as a base file with all stories and we can import them all into this file.
Note: Storybook 5.3.0 and later adopt a filename pattern of: *.stories.js
. To fit this convention, buttonStories.js
should be renamed to button.stories.js
.
You may also encounter a generated 1-Button.stories.js
file for a demo story that uses the same Button
title. To avoid confusion, you can comment the contents of that file out.
Then for every new file created under the stories
directory, we will import them into this file.
Addons with Storybook helps implement extra features to make them more useful and interactive. A full list of all addons available for Storybook can be found on the official site.
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.
We can set up the addon if it’s not already done by default you will need to follow these steps.
Note: If you are using Storybook 5.3.0 or later, for the purposes of this tutorial, you will not need a addons.js
file and can ignore this step.
Install the addon package with this command:
- npm install --save-dev @storybook/addon-actions
Then, add the following content to .storybook/addons.js
:
import '@storybook/addon-actions/register';
Now your Storybook supports addons.
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' }}
/>);
Then run Storybook:
On the tab below you’ll observe an Actions tab
where the action is logged any time we interact with the buttons.
With Storybook, we have the ability to customize the default theme used and Storybook comes bundled with a default light theme. Now, let’s explore 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
}
});
Note: Storybook 5.3.0 and later introduce manager.js
. The steps for theming with this new convention are discussed in the official theming documentation.
With the dark theme configured, we can observe that the entire Storybook theme has switched to the dark theme. At any point, this can be switched back to either a light or dark theme depending on our preference.
We can also define a dynamic theme out of the box if we want a different theme entirely. The first step is to create a file for our theme, within .storybook
folder create a new file called yourTheme.js
. The next step is to generate a new theme using the create()
function from storybook/theming
.
Here is an example of a pink.js
theme:
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 Storybook'
});
Then, we can go ahead and import pink.js
in our Storybook config file.
import pink from './pink';
addParameters({
options: {
theme: pink
}
});
This gives us a completely different theme compared to the previous image.
One feature that comes bundled with Storybook is the fact that we can deploy our Storybook as a static site that we can deploy to 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:
- npm run 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:
- npx http-server .out
:
Note: Your package.json
may feature a build-storybook
script that resembles: build-storybook -s public
. Rather than the specified .out
directory, this outputs the static site files to a storybook-static
directory.
This will serve the content of the folder as a static site.
In this article, we’ve learned how to build interactive components using Storybook and React. Now we have explored 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 frontend 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 official documentation.
You can also find the code for this article on GitHub.
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!