Storybook & Atomic Design – 1.3. – Building Our Stories

If you've followed our setup lesson, you should now have a local Storybook development available on your local machine. In this lesson be covering how we can go about writing and building our own custom stories.

But before that, let's first define what a story is in Storybook.

What is a Story?

Technically, a story is a function that returns something that can be rendered to screen. - https://storybook.js.org/docs/basics/writing-stories/

In the context of Storybook, a story is a visual representation of a component or interface within your design system.

This could include something basic such as a list item or something large like a footer component.

In its most basic form, we would simply return the component to the render of the story. However, we may extend the base functionality of a story to include advanced configuration with the inclusion of data imports and documentation around a component to help aid the telling of the story.

Pre-Config

Our current Storybook structure looks something like this -

- __Storybook__
   - __config__
     -  addons.js
     -  config.js
   - __node_modules__
   - __stories__
     -  0-Welcome.stories.js
     -  1-Button.stories.js
   - .gitignore
   - package-lock.json
   - package.json

I'm not a big fan of this structure though as it implies that stories exist in one directory, with components in another. I'm all for having a dedicated directory for complex stories but when developing a component, it'd be really helpful to have the story coupled to the component.

So this structure won't work, instead, I want to create a new directory which will house atoms, molecules, etc. with each component directory having a React component and story file.

To achieve the new structure, we'll need to modify the config.js file in our config directory to search our new components directory instead of looking in stories.

import { configure } from "@storybook/react";

// automatically import all files ending in *.stories.js
configure(require.context("../components", true, /\.stories\.js$/), module);
- __Storybook__
   - __config__
     -  addons.js
     -  config.js
   - __node_modules__
   - __components__
     -  __atoms__
   - .gitignore
   - package-lock.json
   - package.json

How Do We Write a Story?

To add our first story we'll do the following -

  1. Start our development environment
  2. Create our button component directory
  3. Create our React button component
  4. Create our Storybook story file

Start Storybook

So before we start writing any files or components, let's first get Storybook up and running locally.

We can do this by running the following command in the root directory of our Storybook project.

npm run storybook

You should now have a React Storybook instance development server available at http://localhost:6006

With our Storybook environment spun up on our local machine, we'll now create our button component directory. Storybook recommends keeping your story file nested in the same directory as the React component file it is associated with to keep the documentation coupled with the component.

I agree that the directory structure makes sense, as I tend to keep all style files as siblings within the associated parent component directory, so it would make sense to also keep the documentation in the same directory too.

- __Storybook__
   - __components__
     - __atoms__
       - __button__
         - button.jsx
         - button.stories.js

Create our React Button Component - button.jsx

JSX is a popular templating language associated with React. It's similar to a standard JavaScript file but allows for template highlighting and structures that make sense in the context of React.

For our first story, we'll create a Functional Component in React which will take in props and return a very basic button with the default button browser styles and functionality.

In our component, we are immediately destructuring the props the component is passed and getting access to the children prop value. For anyone unfamiliar, the value of this props is equal to the values found between the components opening and closing tags when we call it later on.

For example, if we used <Button>hello</Button would have the children prop value as hello.

import React from "react";

const Button = ({ children }) => <button className="button">{children}</button>;

export default Button;

Creating our Story File - button.stories.js

With our component available, we now need to add it to our Storybook environment.

This is done with the use of a file with a .stories.js file extension.

The syntax of this file is very similar to our button.jsx file. We first import React to make it available to our file and then import our React Button component so that we can use it to write examples on how the Button may be used in a React application.

Next, we create a basicButton function which returns our Button component with the children prop value of 'Basic Button'. This would then render a default HTML button with Basic Button as the text value.

Finally, we are exporting a default object from our file with two properties.

The first property is the Component we are documenting, so in this example, we would reference the Button component.

The second property is the title of the story, for which we will simply title it 'Button'.

import React from "react";
import Button from "./button";

export const basicButton = () => <Button>Basic button</Button>;

export default {
    component: Button,
    title: "Button"
};

What you should now notice is when you visit - http://localhost:6006/?path=/story/button--basic-button in your browser, is that we now have access to a story titled 'Button' with our story example returning an un-styled, default HTML button element with the text 'Basic Button' within it.

Screenshot of a basic button component in a Storybook window

And there you have it, you've written your first story for your storybook.

We'll be revisiting the button component throughout the next few lessons to extend it with custom functions, styles and icons but for now, I wanted you to get familiar with the process of adding a story to your storybook.

If you still feel a bit confused or wanted to learn more about adding stories, you can do so at Storybooks official documentation - https://storybook.js.org/docs/basics/writing-stories/

In the next lesson, we'll create a global application wrapper that will be injected into all of our stories, allowing us to pass style values that we can use within our component style files.

Continue Reading 📚