One of the greatest parts about React is the giant ecosystem of components created by thousands of devs all over the world.
I'm sure you've wondered at some point, how can I contribute something of my own to this? Is it simple? How can I share only my components without just pasting raw code? I suppose I could just have a project with no UI, but then how would I test my components? π
I'm going to go over how to create and test your UI library. Here we go! π
Enter Storybook π
Storybook is an open source tool that makes creating UI libraries extremely easy. Let's get your Storybook project up and running! πββοΈ
π§ΆNote: I am going to be using yarn throughout this tutorial, however, any package manager works
Let's head over to our terminal and set up a new yarn project
# Creating a new directory to put our project into
mkdir storybook-demo
# Changing our current directory to our project directory
cd storybook-demo
# Setting up a yarn project (feel free to use the -y flag)
yarn init
# Opening our directory in our text editor (I use VSCode)
code .
Now let's open up our package.json
that was created in our directory, if you're using yarn it'll look like this:
{
"name": "storybook-demo",
"version": "1.0.0",
"main": "index.js",
"license": "MIT"
}
Let's head back to our terminal and add React to our project
# Add react and react-dom to devDependencies
yarn add react react-dom -D
Now your package.json
should look something like this:
{
"name": "storybook-demo",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"devDependencies": {
"react": "^17.0.1",
"react-dom": "^17.0.1"
}
}
Sweet! Now let's create an src
folder.
# create an src folder
mkdir src
Cool, we'll mess with the folder structure a little more, but this is sufficient to reliably set up Storybook in our project.
Go ahead and run this in your terminal:
npx sb init
πNote: Make sure you have react in your project before running this command, storybook uses information provided in your package.json
to initialize itself
As you wait for this to work its β¨magicβ¨, you can take a trip over to the Storybook docs to read a little more about it.
One that finishes, you'll notice some differences to your project, let's start by going into our package.json
{
"name": "storybook-demo",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"devDependencies": {
"@babel/core": "^7.13.10",
"@storybook/addon-actions": "^6.1.21",
"@storybook/addon-essentials": "^6.1.21",
"@storybook/addon-links": "^6.1.21",
"@storybook/react": "^6.1.21",
"babel-loader": "^8.2.2",
"react": "^17.0.1",
"react-dom": "^17.0.1"
},
"dependencies": {},
"scripts": {
"storybook": "start-storybook -p 6006",
"build-storybook": "build-storybook"
}
}
Great! Storybook has recognized that we have react in our project (as seen with the @storybook/react
dependency). Also take note of the two new scripts that have been added to our project, we'll look more at the first one later.
If you've never used storybook before, feel free to run this command and explore!
# for yarn
yarn storybook
# for npm
npm run storybook
If you look at your file structure, you'll also notice two new folders have been introduced: .storybook
and src/stories
For the means of this tutorial, we are going to leave .storybook
alone, as all of the default configurations suit our needs. Refer to the docs if you find the need to change things up.
But let's take a look into the src/stories
folder
You'll see something looking like this:
src/stories
| /assets
| button.css
| Button.js
| Button.stories.js
| header.css
| Header.js
| Header.stories.js
| Introduction.stories.mdx
| page.css
| Page.js
| Page.stories.js
Take note of how this is structured, as this is entirely viable Storybook code! However, I think we can make something more robust and more easily scalable by bettering the file structure of our project
So let's delete the contents!
# change to stories directory
cd src/stories
# remove the contents
rm -rf *
We'll come back to that later... let's set up a UI component! We'll be making a simple button, but feel free to make whatever you would like
# change to our src directory (assuming you're in src/stories)
cd ..
# create a components directory
mkdir components
# change to our components directory
cd components
# create a Button.js file in our components directory
touch Button.js
# open Button.js in our editor
code Button.js
For the sake of simplicity, we're going to keep this component pretty barebones, we can iterate more on this later.
// src/components/Button.js
export const Button = () => {
return <button>I am a Button!</button>;
};
Now we need to set up a story for our Button. Let's create a file:
# Go to stories dir (if you're still in src/components)
cd ../stories
# Create a Button.stories.js in our stories directory
touch Button.stories.js
# Open it in our editor
code Button.stories.js
Still with me? Now let's put in some code to test out Storybook
We can think of our story as a mini React project. We'll walk through the basics of making a story, but you can check out the docs on a more in depth explanation of what a story is here
Go ahead and put this into your Button.stories.js
file:
// Button.stories.js
// import React and stories from storybook
import React from "react";
import { storiesOf } from "@storybook/react";
// import our Button component
import { Button } from "../components/Button";
// create our stories
const stories = storiesOf("Button Test", module);
// add to our stories
stories.add("Button", () => {
return <Button />;
});
This simple story is going to just display our Button component that we created earlier, as to maintain simplicity
Also! Since our story behaves like a React app, we need to import React. This also applies if we choose to use hooks.
Now let's see if our story works!
# for yarn
yarn storybook
# for npm
npm run storybook
You should see something like this pop up in your browser:
Great! Now everything is up and running. We can do just about anything we want with our storybook, from creating an entire UI library, to testing out how our different UI components work together.
I'll give a quick (albeit very very simple) example with the Button component that we made. After that I'll send you off on your own! β
// src/components/Button.js
export const Button = ({
bgColor = "lightblue",
children = "Button",
...props
}) => {
return (
<button style={{ backgroundColor: bgColor }} {...props}>
{children}
</button>
);
};
This simple Button component takes in a bgColor
prop, it's children
, and then also passes it's rest of its props
(for instance 'onClick')
Now let's make this do something within our story!
// src/stories/Button.stories.js
import React from "react";
import { storiesOf } from "@storybook/react";
import { Button } from "../components/Button";
const stories = storiesOf("Button Test", module);
stories.add("Button", () => {
const handleClick = () => {
alert("You clicked the button!");
};
return (
<Button bgColor="white" onClick={handleClick}>
This is the Button's children
</Button>
);
});
I added in an onClick
handler, a prop for our bgColor
, and filled in the Button's children with some generic text.
And with our Storybook magic, we've created this! π
I hope this tutorial was helpful to you! I personally plan on using Storybook for creating any UI based libraries I make, what about yourself?
Until then, code on! π©βπ»
PS: Here's the source code
Top comments (1)
very nice tutorial, thank you!