Build Your Own UI Component Library
Tags: react, tailwindcss, storybook, webdev
Published: 2021-08-18 11:31:53

A UI component library is a set of ready-made UI components such as buttons, inputs, dialogs, and so on. They serve as building blocks for layouts. Thanks to their modular nature, we can arrange components in many different ways to achieve unique effects. Each library has a distinctive look and feel, but most of them offer theming, and their components are customizable and reusable.
I will walk you through the process of creating your own UI Component Library using : 

1. React
2. TailwindCSS
3. Storybook
4. NPM

<hr />

## Create a new React project and install TailwindCSS

```bash
npx create-react-app storybook-postcss-tailwind
```

> Initialize TailwindCSS.

```bash
npm install -D tailwindcss@latest postcss@latest autoprefixer@latest
```

- Inside `tailwind.css` file, add the following line:

```css
@tailwind base;
@tailwind components;
@tailwind utilities;
```

> Create `tailwind.config.js` with npx. 
`--full` option scaffold file that matches the default configuration file that Tailwind uses internally.

```bash
npx tailwindcss init --full
```

- Inside `tailwind.config.js` file, add the following configuration in `purge:[]`:

```js
"./src/**/*.{js,ts,jsx,tsx}"}
```

> Install **postcss-cli** and create `postcss.config.js` file.

```bash
npm install -D postcss-cli
```

- Inside postcss.config.js, add the following:

```js
        module.exports = {
		plugins: {
			tailwindcss: {},
			autoprefixer: {},
		},
	};
```
<hr />

## Install Storybook and create a new component

> Initialize Storybook with the following command:

```bash
npx sb init
```

> Create sample component `src/lib/components/Button/Button.js`, with some styling:

```js
	import React from ‘react’
	import PropTypes from 'prop-types'
	
	const Button = ({ label }) => {

		return (
			<div>

				<button 
				className='bg-red-500 text-white text-xl py-4 px-8 rounded-md'>{label}</button>

			</div>
		)
	};
	
	Button.propTypes = {
	label: PropTypes.string.isRequired
	};
	
	Button.defaultProps = {
	label: 'Button'
	};
	
	export default Button
```

> Create `src/lib/components/Button/Button.stories.js` with the following content:

```js
	import React from 'react';
	import Button from './Button'
	
	export default {
		title: 'Example/Button',
		component: Button,
	};
	
	const Template = (args) => <Button {...args} />

	
	export const Default = Template.bind({})
	Default.args = {
		label: 'Button'
	};
```

- Inside `src/lib/index.js`, add the following line:

```js
	import './styles/main.css';
	import Button from './lib/components/Button/Button'
	
	export { 
		Button 
	};
```

<hr />

## Configure `package.json` and additional dependencies

```bash
npm i -D cross-env @babel/cli @babel/preset-env @babel/preset-react 
```

> Create `babel.config.js` file:

```js
	module.exports = function (api) {
	api.cache(true);

	const presets = [ "@babel/preset-env", "@babel/preset-react" ];
	const plugins = [ "macros" ];

		return {
			presets,
			plugins
		};
	}
```

> To avoid any React conflict, you can move the following React dependencies to a peer dependency:

```js
"peerDependencies": {
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-scripts": "4.0.3"
}
 ```
<br />

- Inside `package.json`, add the following scripts for  TailwindCSS:

```js
	"scripts": {
		"build:tailwind": "postcss src/lib/styles/tailwind.css -o src/lib/styles/main.css",
    	"build:tailwind-prod": "cross-env NODE_ENV=production postcss src/lib/styles/tailwind.css -o src/lib/styles/main.css"
	},
```
<br />

- To prepare for production we need to add the following script at the top of `package.json`:

```js
	"private": false,
	"main": "dist/index.js",
	"module": "dist/index.js",
	"files": [
		"dist",
		"README.md"
	],
```
<br />

- Still inside `package.json`, add the following under `scripts`:

```js
	"scripts": {
		"clean": "rimraf dist",
   		"compile": "npm run clean && cross-env NODE_ENV=production babel src/lib/ --out-dir dist --copy-files"
	},
```
<hr />

## Building for production and Publishing to **npm**
<br />

> Build tailwindcss for production:

```bash
npm run build:tailwind-prod
```

- Compile components for production:

```bash
npm run compile
```

- If you don't have a *npm* account, create one.

- Execute the following command:

```bash
npm login
```

- Execute the following command:

```bash
npm publish
```

*That's it!* We managed to get a simple UI Library using Storybook and TailwindCSS. This is one option how can you create UI Components Library. From here you can:
1. Add more components
2. Create stories for components
3. Create test cases for components
4. And much more...


## Appendix

- [TailwindCSS](https://tailwindcss.com/)
<br />
- [Storybook](https://storybook.js.org/)
<br />
- [React](https://reactjs.org/)
<br />
- [NPM](https://www.npmjs.com/)
<br />
- [GitHub](https://github.com/minime89-maker/react-storybook-tailwindcss_template)