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.
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.
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.
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';
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.
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.
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.
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.
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.
Before publishing, make sure to update the name
, version
, 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
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.
Articles, resources, and pieces of my mind... 🧠