While component-based UI libraries like React simplify web development, they also introduce new complexities like testing and debugging.
React components are built to support several use cases and are often interdependent, which means that if you make a wrong turn, you risk breaking the application down.
Storybook enables developers to build UI components in isolation using independent building blocks. With Storybook, you can quickly create UI components using your favorite framework while also providing a decluttered interface to work on each component.
In this article, we’ll go through:
So, are you ready to go on an adventure with me?
Let’s go!
What is Storybook?
Storybook is a development environment for UI components that enables you to create and showcase components in an environment outside your main application. This allows you to work on one module at a time and develop entire UIs without the need for a complex dev stack.
Storybook also enables you to document, reuse, and test user interface components. In addition to that, it makes building web applications faster and more efficient.
The tool has an extensive plugin ecosystem that can help extend and fine-tune your application. Also, it integrates with the most popular JavaScript frameworks such as React, Vue, and even Ruby.
Should you use Storybook with React?
Long story short, yes.
Storybook is a compelling, visual way to document UI components and design systems alongside React.
Beyond that, it is an excellent tool for presenting technical documentation and demoing implementation details. It also helps with testing new configurations before users have the chance to interact with them.
But that’s not all. Storybook has plenty of benefits for developers looking to build better components:
Simplifies component building: Storybook creates “stories” or small components that run independently and that you can then add to your application.
Prevents you from duplicating effort: Sometimes, devs create a component only to find that there’s already something similar in the codebase. With Storybook, each component is documented and accessible to others, preventing effort duplication.
Creates a living style guide: Storybook’s code templates are pieces of living code you can use and develop from, ensuring that developers don’t use mockups or similar fallible templates when building a web application.
Builds components in isolation: Developing in isolation ensures that you only focus on the component you’re building. You don’t need to think about the other parts of your app because every component you build in Storybook lives in its own folder where there are files for implementation and testing.
Building Your First Storybook Components for React
Storybook uses the component-driven development (CDD) methodology to create UI components. Following this methodology, you can build modularly, starting with essential components and progressively combining them into complex screens and apps.
Additionally, components enable you to use interchangeable pieces and swap them without affecting the application’s business logic, allowing you to take components apart and recompose them into different UIs as needed.
Now that you know about component-driven development and have seen the benefits of Storybook, let’s get cooking. If you follow this recipe, I’m sure you’ll get a tasty component.
Prerequisites
This is what you need to get started with Storybook:
Basic understanding of React, JavaScript, and TypeScript
A code editor like Visual Studio Code
Node.js installed on your machine
npm installed on your machine
How to Install Storybook
One of the cool things about Storybook and React is that they play well together. In fact, Storybook detects you’re using Create React App and installs the dependencies for you. That’s helpful, especially if you’re a beginner.
In this tutorial, we’re using Next.js. Of course, you can use Vue, Angular, and other frameworks, but we’ll use React for the sake of simplicity.
For those of you who aren’t already familiar with Next.js, it’s a popular React framework that supports both static and server-side rendered pages out of the box.
1. Creating a new React app with Next.js
Before we start our adventure with Storybook, we’ll first need to create an up and running Next.js app so that we can install Storybook in it.
If you don’t already have a React application to which you would like to add Storybook, you can first create one by initializing a Next.js application. In your terminal, run the following:
npx create-next-app <your-app-name>
The command above will generate a new Next.js application in the directory in which it was run and will have the same name you provided (<your-app-name>
) when running the prompts.
For example, if you named it nextjs-storybook-example
, you should run the following in your terminal to navigate to it:
cd nextjs-storybook-example
2. Initializing Storybook in your React app
Now that we have our React application up and running, we’ll need to install and set up our local instance of Storybook.
Once in the directory of the application, run the following command to install Storybook:
This will quickly set up the boilerplate needed for a working Storybook instance. Npx is the npm package runner installed alongside npm since npm@5.2.0.
If you’re curious to learn more about npx, this Node.js guide has more information.
Once we’ve set up our Storybook instance, let’s make sure that all the required dependencies are installed by running:
3. Running Storybook locally
Now let’s look at our instance of Storybook by running:
Once the command has successfully run, a working version of Storybook should start running at http://localhost:6006/.
4. Creating your first component for Storybook
Let's create a banner component to add to our application. To do so, let's go to our code editor with our project folder opened, we can see a /src
directory with a /stories
folder inside, which was autogenerated when we ran sb init.
In this folder create a file named Banner.jsx
.
In this file, let’s add the following code:
/** @jsxImportSource @emotion/react */
import React from "react";
export default function Banner({ variant = "info", children }) {
return <aside> {children} </aside>;
}
Banner.propTypes = {
variant: "info" | "congrats" | "documentation" | "danger",
};
The PropTypes
or TypeScript
types are used by Storybook to autogenerate some of the documentation in stories.
Now that we have our unstyled component, let’s give it some flavor with a bit of CSS.
A CSS object can be used to apply different styles on different variants dynamically. Emotion, for instance, is a library that enables writing CSS objects with JavaScript. We will use it in this tutorial to help us style the components.
You can install Emotion by typing the following command into Node:
npm install @emotion/react
In order for Emotion to process the CSS in JS properly, we should add the following line to the top of the Banner.jsx
file:
/** @jsxImportSource @emotion/react */
Below is an example of how different styles can be applied to a React component based on the value of a prop. This will enable our banner component to change style depending on the state it’s in.
/** @jsxImportSource @emotion/react */
import React from "react";
export default function Banner({ variant = "info", children }) {
const beforeStyles = {
width: 35,
height: 35,
display: "inline-flex",
justifyContent: "center",
position: "absolute",
left: "-1.2rem",
borderRadius: "50%",
alignItems: "center",
top: "-0.8rem",
};
const variantStyles = {
info: {
borderLeft: "4px solid #b4aaff",
backgroundColor: "rgba(224, 226, 255, 0.5)",
color: "#2a2135",
"&:before": {
content: '"🔑"',
backgroundColor: "#b4aaff",
...beforeStyles,
},
},
danger: {
borderLeft: "4px solid #ff7828",
backgroundColor: "rgb(253, 236, 234)",
"&:before": {
content: '"⚠️"',
backgroundColor: "#ff7828",
...beforeStyles,
},
},
congrats: {
borderLeft: "4px solid #72bc23",
backgroundColor: "rgb(249, 253, 234)",
"&:before": {
content: '"🎉"',
backgroundColor: "#72bc23",
...beforeStyles,
},
},
documentation: {
borderLeft: "4px solid #44a9ba",
backgroundColor: "rgb(234, 248, 253);",
"&:before": {
content: '"📚"',
backgroundColor: "#44a9ba",
...beforeStyles,
},
},
};
return (
<aside
css={{
margin: "1.5rem auto",
borderRadius: "0px 10px 10px 0px",
padding: "0.8em 1em",
lineHeight: "1.2",
textAlign: "center",
position: "relative",
clear: "both",
maxWidth: "500px",
...variantStyles[variant],
}}
s
>
{children} {" "}
</aside>
);
}
Banner.propTypes = {
variant: "info" | "congrats" | "documentation" | "danger",
};
This will change the style of our banner component from this:
To this:
The variantStyles
object has keys with specific styles for each of the variants the Banner supports. I.e., If the value of the variant prop is “documentation”, then we’ll apply the styles contained in variantStyles[documentation]
aside.
Here’s an example of the variantStyle
object:
{ borderLeft: "4px solid #44a9ba", backgroundColor: "rgb(234, 248, 253);", "&:before": { content: '"📚"', backgroundColor: "#44a9ba", }, },
5. Creating our first story
After adding a file to the /stories
folder, we need to add an associated story file to view the component in Storybook.
This new file should be added to the stories folder with the name Banner.stories.jsx
to be adequately detected by your default Storybook configuration.
In this example, I created Banner.stories.jsx
and imported the Banner component created in the previous step.
I also added metadata such as "info," "congrats," "documentation," and "danger" to the default export as Storybook uses this information to list stories and provide additional details about the particular parts.
Within Banner.stories.jsx
, I also defined some constants that render the Banner with different props. Storybook will automatically convert them into stories with the same name as the constant.
import React from "react";
import Banner from "./Banner";
export default { title: "Example/Banner", component: Banner };
export const Info = () => (
<Banner variant="info">
{" "}
{" "}
<p>
{" "}
This is an example of an info banner to display important
information. {" "}
</p>{" "}
{" "}
</Banner>
);
export const Danger = () => (
<Banner variant="danger">
{" "}
<p>This is an example of a danger banner to display warnings.</p> {" "}
</Banner>
);
export const Congrats = () => (
<Banner variant="congrats">
{" "}
<p> This is an example a congrats banner to celebrate a win!</p> {" "}
</Banner>
);
export const Documentation = () => (
<Banner variant="documentation">
{" "}
{" "}
<p>
{" "}
This is an example a documentation banner to highlight relevant reading
materials and documentation.{" "}
</p>{" "}
{" "}
</Banner>
);
6. Viewing a story in Storybook
Let’s revisit the Storybook instance and navigate to the component we just created.
In my instance, I selected Banner from the side navigation and clicked on docs, which directed me to http://localhost:6006/?path=/docs/example-banner--info.
This particular documentation view contains a summary of all of the various Banner stories that we defined in the previous steps and highlights their visual differences. It also includes a button “Show code” that can be toggled to view the JSX and generate that particular element.
7. Using a story in our React app
To use the story in our React application, we can import the created Banner.jsx
file into the index.js
folder in your Next.js installation.
import Banner from "../stories/Banner.jsx";
Then we can use the component the same way we would normally do by writing an instance of it with the appropriate props and children's HTML like below:
<Banner variant="info">
<p>This is an example of how we can use our components from Storybook in a NextJS application. JSX components that are defined in Storybook can be imported/exported like regular JSX components. If you need to import components from Storybook in external applications then you should explore publishing a NPM package that contains the relevant components.</p>
</Banner>
Adding Banner.jsx
above the header of our Next.js’ index.js
will render a page that looks something like this:
The example above shows how to import components from Storybook when the stories are co-located within the same project.
However, if you would need to import them from Storybook in an external application, you should try publishing an npm package that contains exports of the Storybook components.
This will enable you to import them across projects, but for the sake of simplicity, we’ve built everything in a single project.
Now that we have a styled component up and running let’s dive right into the Storybook features that allow you to build beautiful UIs.
Storybook features
Now that you created and styled your first component, let's see what some of the most popular features Storybook has. You’ll find additional links with tutorials and resources at the end of each section if you want to dive deeper.
Stories
A story shows how a UI component should look on your browser. With Storybook, you can write multiple stories based on every change you want to make to your component. This means that rather than changing elements in the DOM, Storybook updates the information a user sees based on the stories you’ve created.
Stories act as instructions that you give to your components. They also serve as a failsafe in case the changes you’ve made introduce bugs or issues to your code.
Additional Resources
Design systems
A design system is a collection of reusable components that can be assembled together to build applications and act as a single source of truth for every person involved in the project.
Storybook’s design systems bridge the gap between UX/UI designers, developers, and business stakeholders. By creating design guidelines with design patterns, rules, and roles, Storybook helps prevent code and design inconsistencies developing and deploying software products at scale.
Additional Resources
Add-ons
Add-ons enable you to extend a Storybook installation with features and integrations built by other community members. There are many different kinds of add-ons, and it’s fairly simple to customize Storybook using addons and unlock the true power of the tool.
Addons are typically classified into two categories, UI-based addons that extend the development workflow and preset add-ons that help you integrate the tool with other technologies and libraries.
Additional Resources
Testing
Storybook simplifies testing and debugging by providing developers with an environment for testing components in isolation. The easiest way to test Storybook is by manually spot-checking, but the tool also comes with test runners and integrations to run even better tests.
Storybook supports different kinds of tests such as visual tests, accessibility tests, interaction tests, and snapshot tests.
Additional Resources
Deployment
Storybook enables teams to review and collaborate on each other’s works in progress, allowing different stakeholders to check the UIs without requiring a local dev environment.
Using Storybook as part of your development process ensures that the team will gather feedback quickly by sharing pull requests over Slack or using third-party tools like Chromatic.
Additional Resources
Conclusion
My adventure with Storybook turned out to be a bit like Bilbo’s. Rather than a night out with Gandalf, I ended up angering a dragon, but like our Hobbit friend, I managed to get out with some treasure.
Storybook has quickly gained popularity with developers, and it’s easy to see why. The ability to work on isolated components in a clean interface is a huge time-saver, and the ability to visually test your code is also something too good to pass by.
With its simple interface and wide range of features, you can quickly put together prototypes or entire UIs without having to worry about setting up a complex development environment.
If you've used Storybook already, I’d love to hear what you think in the comments.