Creating a React UI Library using Storybook and Tailwind

by

Timurtek Bizel

1. Introduction

Developing a consistent and reusable UI library is crucial to modern web development, enabling efficient and streamlined development processes. This article will explore how to create a robust UI library using React, Storybook, TypeScript, Tailwind, and NPM. We will guide you through the entire process, from setting up the environment to publishing your library.

2. Setting up the environment

First, let’s set up our development environment. We must install Node.js and NPM (Node Package Manager) to do this. If you don’t have them installed already, head over to https://nodejs.org/en/download/ and follow the instructions for your platform.
Once Node.js and NPM are installed, please create a new folder for your UI library and navigate to it in your terminal or command prompt. Run the following command to create a new React project:

npx create-react-app my-ui-library --template typescript

This command will create a new React project with TypeScript template. Replace my-ui-library with your desired project name.

3. Installing dependencies

Next, we need to install the required dependencies. Navigate to your project folder and run the following command:

cd my-ui-library

Install Storybook, Tailwind, and their required dependencies by running:

npx sb init
npm install tailwindcss@latest postcss@latest autoprefixer@latest

This will set up Storybook and install Tailwind CSS, PostCSS, and Autoprefixer.

4. Configuring Tailwind CSS

To configure Tailwind CSS, create a tailwind.config.js file at the root of your project and add the following content:

module.exports = {
  purge: ['./src/**/*.{js,jsx,ts,tsx}', './public/index.html'],
  darkMode: false, // or 'media' or 'class'
  theme: {
    extend: {},
  },
  variants: {
    extend: {},
  },
  plugins: [],
}

Next, create a postcss.config.js file in the project root, with the following content:

module.exports = {
  plugins: {
    tailwindcss: {},
    autoprefixer: {},
  },
}

Finally, import Tailwind CSS in your src/index.css file:

@import 'tailwindcss/base';
@import 'tailwindcss/components';
@import 'tailwindcss/utilities';

In your Storybook configuration folder (.storybook), open the preview.js file (or create it if it doesn’t exist), and import the newly created CSS file:

import '../src/index.css';

5. Creating UI components

Now that our environment is set up, let’s create some UI components. Start by creating a new folder named components inside the src directory. Inside the components folder, create a new folder for each UI component you want to create.
For example, let’s create a simple button component. Create a new folder called Button inside the components directory, then create two files within it: Button.tsx and Button.stories.tsx.
Open Button.tsx and create a functional React component that renders a button with Tailwind CSS classes:

import React from 'react';

export interface ButtonProps {
  text: string;
  type?: 'primary' | 'secondary';
  onClick?: () => void;
}

export const Button: React.FC<ButtonProps> = ({
  text,
  type = 'primary',
  onClick,
}) => {
  const buttonClasses =
    type === 'primary'
      ? 'bg-blue-500 hover:bg-blue-600 text-white'
      : 'bg-gray-200 hover:bg-gray-300 text-black';

  return (
    <button className={`px-4 py-2 rounded ${buttonClasses}`}
  onClick={onClick}
>
  {text}
</button>
 );
};

This component accepts `text`, `type`, and `onClick` props, and applies appropriate Tailwind CSS classes based on the `type` prop.

6. Creating Storybook stories

Now, let’s create a Storybook story for our button component. Open `Button.stories.tsx` and add the following content:

import React from 'react';
import { Meta, Story } from '@storybook/react';
import { Button, ButtonProps } from './Button';

export default {
  title: 'Components/Button',
  component: Button,
} as Meta;

const Template: Story<ButtonProps> = (args) => <Button {...args} />;

export const Primary = Template.bind({});
Primary.args = {
  text: 'Primary Button',
  type: 'primary',
};

export const Secondary = Template.bind({});
Secondary.args = {
  text: 'Secondary Button',
  type: 'secondary',
};

This file defines two stories, one for the primary and one for the secondary button styles, using the Button component we created earlier.

7. Running Storybook

To run Storybook, execute the following command in your terminal:

npm run storybook

This will start the Storybook development server and open it in your default web browser. You can now see your button component in the Storybook interface, with primary and secondary variations.

You can delete the example files if you want to by deleting the folder: src/stories

You can also delete these additional files under src: App.css, App.test.tsx, App.tsx,index.tsx, logo.svg, react-app-env.d.ts, reportWebVitals.ts, setupTests.ts.

8. Creating additional components

Repeat steps 4 and 5 for each additional UI component you want to create. Make sure to organize them in separate folders within the components directory.

9. Building the library

Once you’ve created all your desired components, it’s time to build the library. First, let’s create a src/index.ts file to export all our components:

export { Button } from './components/Button/Button';
// Export other components here

Create a file named tsconfig.build.json, and add the following code.

{
    "extends": "./tsconfig.json",
    "compilerOptions": {
      "outDir": "lib",
      "noEmit": false,
      "declaration": true,
      "emitDeclarationOnly": true
    },
    "exclude": ["node_modules", "src/**/*.stories.tsx", "src/**/*.test.tsx"]
  }
  

Now, let’s update our package.json file to include a build script. Add the following line to the scripts section:

"build": "tsc -p tsconfig.build.json",

This script will build your React app and generate TypeScript declaration files in the lib directory.

10. Publishing to NPM

Before publishing, make sure to update the nameversion, and description fields in your package.json file. Also, add the main and types fields to specify the entry points for your library:

"main": "lib/index.js",
"types": "lib/index.d.ts",

Remove the ‘private’ field from the package.json to publish it.

"private": true,

Once you have updated the package.json, run the following command to build your library:

npm run build

Before publishing, make sure your package name is unique.

"name": "my-custom-react-ui-library",

Finally, publish your library to NPM:

npm login
npm publish

Conclusion

Congratulations! You have successfully created a React UI library using Storybook, TypeScript, Tailwind, and NPM. You can now use your library in other projects, share it with others, and iterate on its development as needed. This setup provides a solid foundation for building scalable and maintainable UI libraries in React.

Timurtek Bizel

UX UI Engineer

I'm a passionate UX/UI Engineer who excels at bridging the gap between design and development teams. With fluency in both design and development languages, I bring the luxury of seamless communication and collaboration to every project. I am well-versed in translating design concepts into functional and visually captivating user interfaces. Additionally, my expertise extends beyond traditional development methods.

Blog posts

Articles, resources, and pieces of my mind... 🧠