Building a front end project with React, TailwindCSS and Storybook

John Clarke
Storybook
11 min readMar 19, 2021

--

All of the code related to the post can be found in my GitHub as a starting point for your projects.

The what and the why

I’ve been a back end developer for most of my twenty five year plus career, working away behind the scenes and generally avoiding having much at all to do with anything front end. Recently, on a side project I wanted to put together something modern, responsive, and reasonably professional looking. Not having worked in the browser for a long time, since the late 90’s, I knew things had come a long way, and that I was going to be on some kind of learning curve.

To make things as easy for myself as possible, I wanted to put together a development stack that got me up and running as quickly as possible, made the mystic art of CSS as easy as possible, and gave me a way of rapidly developing, visualising, and iterating on the design of my components. I decided on the following stack:

  • React. This has a great community, with a lot of useful online resources. Create React App made getting a boilerplate project up and running simple, and I could be hacking away very quickly.
  • Tailwind. I watched a couple of Adam Wathan’s YouTube videos where he rebuilds popular sites with Tailwind, and I knew straight away it was for me. Heck, I even mostly got flex-box thanks to its intuitive, utility-first CSS classes. Enough help to allow me to build what I could see in my mind, without being so opinionated I spent all my time working around how it thought things should look. Perfect!
  • Storybook. For me, Storybook was the biggest part of the puzzle. I really wanted to build ‘component first’, as that matches how I tend to work on backend code, with the ability to visualise and test components independently as I worked on them. Being new to Tailwind and CSS I also wanted rapid feedback loops, as I knew there was going to be a lot of learning, iterating, and experimenting. It didn’t take me long to realise that Storybook enabled this (and a whole lot more), and really became the glue that held the stack together.

Having decided on the elements of my development stack, I needed to get them to work together. It’s actually not too bad, but there are a few ‘gotchas’ that took some working out, so in the hope of saving others some time and headaches, here’s how I put it all together.

Get started

To get started we need a React application. Everything in this post can be applied to a pre-existing React app, but for this walk-through we’ll start with a fresh from the box React app with nothing much in it. The simplest way to scaffold up a new React application is with Create React App, which is as simple as running the following

npx create-react-app rst-app
cd rst-app
npm start

This will create a default React app, run up a development server and open the app in a new browser tab for you to prove everything is working correctly.

CRA’s development server in action

Install Storybook

With that done, we can move on to setting up the rest of our stack, starting with Storybook. The good news is that getting Storybook into the project is really simple; we can get started with a single command

npx sb init

Before we move on, let’s take a quick look at what that’s done to our project

The Storybook initialiser has recognized we have a React app, and has set itself up for it. The config files in the .storybook folder are available for us to customize down the line if we need to, and the src/stories directory contains some example stories we can use to check everything’s working.

Storybook has added a couple of new scripts to our package.json file, one to run a development server for Storybook, and one to build a Storybook site that the wider team can access. We’ll run up the dev server for now, just issue the command

npm run storybook

Storybook will start the dev server and open in your browser.

Storybook’s development server and sample components

This demonstrates the heart of what Storybook gives us; a straightforward experience that allows us to develop our front end components in isolation from one another, check how they look and work, and then combine them into our finished application, all in one project.

Of course, once you have Storybook running it can do so much more, like snapshot testing and auto-generating documentation for the components that can be shared with a team. We won’t be touching that in this post, but checkout the Storybook site for lots more ideas. For now, let’s move on to installing Tailwind, setting up the React build for it, and integrating it with Storybook.

Install Tailwind

Installing Tailwind for React is a little more involved than Storybook, as it needs specific versions of some of the tooling in order to work. Let’s start by getting them all installed, then we can breakdown what they do and why we need them

Yarn add @tailwindcss/postcss7-compat autoprefixer@9 postcss@7 craco

The first package we’ve installed is Tailwind itself, which gives us full access in our code to all of that CSS utility-first goodness that Tailwind is renowned for. We need to make a couple of tweaks to configure this; first we need to add a Tailwind configuration file to the root of the project, in a file called tailwind.config.js

And then we can update the app’s CSS file to pull in the Tailwind classes. You can find this in the src directory, in the file index.css. Delete all the classes defined in there, and add the following in its place

With this done, we can start writing components using Tailwind, which is awesome. However, if we do we’ll quickly spot a couple of pretty big issues. First they won’t work properly in Storybook, and they won’t work properly in the app itself either. Much sadness, but fortunately not too hard to fix!

Storybook is running, but isn’t using Tailwind’s styling (yet)

Configure PostCSS and AutoPrefixer

PostCSS and AutoPrefixer are key to this; AutoPrefixer will add vendor specific prefixes to the CSS where needed, and Post CSS handle the post-processing of CSS that Tailwind needs. This is the first ‘gotcha’ in the process, we need to ensure that we have version 7 of PostCSS installed, as at the time of writing (March ’21) the latest version wasn’t compatible.

The next challenge is that, in order to be as simple as possible, Create React App’s build process is basically closed, so we can’t easily add steps to it. We could eject the app, but that removes a lot of the benefits of using CRA in the first place, so we really want to avoid that if we can. Enter CRACO to save the day.

CRACO provides a way we can wrap the CRA build process, and use configuration to add additional processes. First we need to add the following configuration in a file called craco.config.js in the project root

This runs PostCSS after the build, using the settings for Tailwind and Autoprefixer.

Then we update the scripts section of the package.json file to use CRACO to run the CRA scripts, like this

“scripts”: {
“start”: “craco start”,
“build”: “craco build”,
“test”: “craco test”,
“eject”: “craco eject”,
“storybook”: “start-storybook -p 6006 -s public”,
“build-storybook”: “build-storybook -s public”
}

At this point we have Tailwind installed, and it’ll work just fine for our app, but if we look at components in Storybook, they still won’t be styled properly. So we’re close, but not quite there just yet.

The reason Storybook doesn’t render our Tailwind styling at the moment is that it also has a build process, and right now that isn’t running PostCSS or AutoPrefixer as it doesn’t know that we need it. Fortunately, the nice folks at Storybook gave us a simple way to fix that, through the main.js file in the .storybook directory. Take the code below, and replace the contents of the main.js file with it

The additional code added to the end of the file tells Storybook to run the same post process when it builds that CRACO did for us when the app built. So now we have all that Tailwind loveliness working for us in Storybook.

Build a component with Tailwind and Storybook

With our development stack and app built for us, let’s see what it can do, and prove we’ve wired it all up right, by reworking the default CRA ‘spinning logo’ app using components, one for the logo and one for the text, Tailwind and Storybook. You can find the code for this on GitHub.

After setting the app as described so far, I removed the Storybook example components, the boilerplate styling, and the contents of the app.

I like to store the stories for each component in the same location as the component itself, as I think this makes them simpler to manage, it also helps maintain the cohesion of each component.

How I structure my components

When I start creating a new component, my first move will be to create a directory structure like that shown in the image. The CSS file simply pulls in the root index.css file so I have access to Tailwind’s classes. I’ll create a simple React functional component in my main .js file, usually just rendering a div tag with the name of the component as text within it. I also create an index.js that simply re-exports it; this makes it much easier for components to import, as they can just import the folder, and not have to remember to import a specifically named .js file. Finally I’ll create a .stories.js file to define the stories for the component. I can then check the Storybook UI to make sure my component shows up and renders, and then start adding the stories that I want to the file. By creating the simplest component implementation and integrating with Storybook right up front, then defining stories before the implementation, I empower my story first development flow, that means as I build out the implementation in the component I can use Storybooks UI at each stage to ensure the component always looks, and works, in the way that I want.

You don’t have to structure the code like this, of course, so long as you use the .story.js naming convention Storybook will find your stories in whichever location you choose.

Using this approach I built a pair of components, one for the logo, and one for the call to action text and link. These are pretty simple, and can be found in the src/components folder. All the styling is, of course, handled by Tailwind, including the animation to spin the logo.

Tailwind makes adding the animation to the logo very easy, thanks to its pre-build animation utility classes, and the ease with which we can modify them. Initially I added the animate-spin class the the SVG logo in my component, but when I looked at it in Storybook I could see that it was spinning so fast it looked like it might fly off the screen! The great benefit of using Tailwind was that in order to slow it down I only had to make a couple of pretty small changes. First up, I modified the tailwind.config.js file as shown, to extend the existing animation classes with a new animate-spin-slow class that takes more time to complete the full animation cycle. I then applied the new class to the logo component, and using Storybook to visualize it, played with the cycle time until I liked what I saw. The ability to constantly visualize changes in Storybook is a great advantage when tweaking styling like this.

I had decided that I wanted the ability to render it at a variety of sizes, from small to extra-large. So, when I was creating the stories for the logo component I created a story for the component at each size, and also added a control that would allow me to manually set the size property while visualizing the component in Storybook. Controls are a great addition to your stories as they provide a visual mechanism to interact with your components. For developers this is useful for manually testing and visualising the various states of the component. As the team expands it’s even more useful as your designers can also jump into Storybook to understand the components, and how they’re various modes affect how they are displayed, and where they might be used within the design of new features.

The logo component in Storybook, showing the control for setting the size

Now when we run up Storybook, we’ve got a catalog of all of our components to work with with stories showing the different options, and controls to allow us to see what they can do. From here we can build out snapshot testing, accessibility auditing, and all the other great addons that are available for Storybook.

A fully Tailwind styled React component in Storybook

Conclusion

I’ve been really pleased with the way this all came together, and how it’s enabled my journey into the world of modern web app development. There’s no doubt at all that using Storybook has been key to the speed with which I’ve gone from zero to… well, not quite hero, but at least someone who can get a front end up together!

Component first development driven through Storybook works really well for me. Generally I’ll build some rough stories before I start seriously building out the component, in a similar way to writing unit tests before my components on the back-end. By creating the stories first I’m forced to think about the different use-cases for each component, and how best to support them. Once the stories capture that, I can work on the component while using Storybook to visualize what I’m building in isolation.

The other great thing about Storybook is that it’s able to grow with me. I started using it as a tool that helped me learn, then build out the app I wanted. Now I’m starting to look at what’s next: testing with Chromatic and running accessibility audits as part of my build process.

--

--

John Clarke
Storybook

Director of Software Development; Agile and GitOps evangelist. Currently building great software with my awesome team!