DEV Community

Cover image for Build Your Own UI Component Library
Minja
Minja

Posted on

Build Your Own UI Component Library

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

Create a new React project and install TailwindCSS

npx create-react-app storybook-postcss-tailwind
Enter fullscreen mode Exit fullscreen mode

Initialize TailwindCSS.

npm install -D tailwindcss@latest postcss@latest autoprefixer@latest
Enter fullscreen mode Exit fullscreen mode
  • Inside tailwind.css file, add the following line:
@tailwind base;
@tailwind components;
@tailwind utilities;
Enter fullscreen mode Exit fullscreen mode

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

npx tailwindcss init --full
Enter fullscreen mode Exit fullscreen mode
  • Inside tailwind.config.js file, add the following configuration in purge:[]:
"./src/**/*.{js,ts,jsx,tsx}"}
Enter fullscreen mode Exit fullscreen mode

Install postcss-cli and create postcss.config.js file.

npm install -D postcss-cli
Enter fullscreen mode Exit fullscreen mode
  • Inside postcss.config.js, add the following:
        module.exports = {
        plugins: {
            tailwindcss: {},
            autoprefixer: {},
        },
    };
Enter fullscreen mode Exit fullscreen mode

Install Storybook and create a new component

Initialize Storybook with the following command:

npx sb init
Enter fullscreen mode Exit fullscreen mode

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

    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
Enter fullscreen mode Exit fullscreen mode

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

    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'
    };
Enter fullscreen mode Exit fullscreen mode
  • Inside src/lib/index.js, add the following line:
    import './styles/main.css';
    import Button from './lib/components/Button/Button'

    export { 
        Button 
    };
Enter fullscreen mode Exit fullscreen mode

Configure package.json and additional dependencies

npm i -D cross-env @babel/cli @babel/preset-env @babel/preset-react 
Enter fullscreen mode Exit fullscreen mode

Create babel.config.js file:

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

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

        return {
            presets,
            plugins
        };
    }
Enter fullscreen mode Exit fullscreen mode

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

"peerDependencies": {
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-scripts": "4.0.3"
}
Enter fullscreen mode Exit fullscreen mode
  • Inside package.json, add the following scripts for TailwindCSS:
    "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"
    },
Enter fullscreen mode Exit fullscreen mode
  • To prepare for production we need to add the following script at the top of package.json:
    "private": false,
    "main": "dist/index.js",
    "module": "dist/index.js",
    "files": [
        "dist",
        "README.md"
    ],
Enter fullscreen mode Exit fullscreen mode
  • Still inside package.json, add the following under scripts:
    "scripts": {
        "clean": "rimraf dist",
        "compile": "npm run clean && cross-env NODE_ENV=production babel src/lib/ --out-dir dist --copy-files"
    },
Enter fullscreen mode Exit fullscreen mode

Building for production and Publishing to npm

Build tailwindcss for production:

npm run build:tailwind-prod
Enter fullscreen mode Exit fullscreen mode
  • Compile components for production:
npm run compile
Enter fullscreen mode Exit fullscreen mode
  • If you don't have a npm account, create one.

  • Execute the following command:

npm login
Enter fullscreen mode Exit fullscreen mode
  • Execute the following command:
npm publish
Enter fullscreen mode Exit fullscreen mode

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

Discussion (0)