Skip to main content

Creating a Customizable React Component Library with Vite and Pure CSS

· 3 min read
Sahil Phondekar
Sr. Software Engineer @Everestek

Building a reusable React component library can streamline UI development across multiple projects. In this blog, we'll create a customizable React component library using:

  • Vite (for fast builds)
  • Pure CSS (for styling)
  • CSS Modules (for scoped styles)

Step 1: Project Setup

1. Initialize the Project

mkdir react-component-library  
cd react-component-library
npm init -y

2. Install Dependencies

npm install react react-dom  
npm install vite @vitejs/plugin-react --save-dev

3. Configure Vite (vite.config.js)

import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';

export default defineConfig({
plugins: [react({
include: '**/*.{jsx,tsx}',
})],
build: {
lib: {
entry: 'src/index.js',
name: 'ReactComponentLibrary',
fileName: (format) => `react-component-library.${format}.js`,
formats: ['es']
},
rollupOptions: {
external: ['react', 'react-dom'],
output: {
globals: {
react: 'React',
'react-dom': 'ReactDOM'
}
}
},
cssCodeSplit: false
}
});

Step 2: Create a Reusable Button Component

1. Folder Structure

src/
├── components/
│ ├── Button/
│ │ ├── Button.jsx
│ │ ├── Button.module.css
│ │ └── index.js
│ └── index.js
└── index.js

2. Button Component (Button.jsx)

import React from "react";
import styles from "./Button.module.css";

const Button = ({
children,
variant = "primary",
size = "medium",
onClick,
className = "",
disabled = false,
}) => {
const buttonClasses = [
styles.btn,
styles[variant],
styles[size],
disabled ? styles.disabled : "",
className,
]
.filter(Boolean)
.join(" ");

return (
<button className={buttonClasses} onClick={onClick} disabled={disabled}>
{children}
</button>
);
};

export default Button;

3. CSS Module (Button.module.css)

.btn {
border: none;
border-radius: 4px;
cursor: pointer;
font-family: inherit;
font-weight: 500;
transition: all 0.2s ease;
display: inline-flex;
align-items: center;
justify-content: center;
}

/* Variants */
.primary {
background-color: var(--primary-color, #4a6bff);
color: white;
}

.primary:hover {
background-color: var(--primary-hover, #3a5bef);
}

.secondary {
background-color: var(--secondary-color, #f0f2f5);
color: var(--text-color, #333);
}

.secondary:hover {
background-color: var(--secondary-hover, #e0e2e5);
}

/* Sizes */
.small {
padding: 6px 12px;
font-size: 12px;
}

.medium {
padding: 8px 16px;
font-size: 14px;
}

.large {
padding: 12px 24px;
font-size: 16px;
}

/* Disabled state */
.disabled {
opacity: 0.6;
cursor: not-allowed;
}

Step 3: Bundle & Publish to npm

1. Export Components (src/index.js)

export { default as Button } from './components/Button';

2. Build the Library

npm run build

3. Publish to npm

npm login
npm publish --access public

Step 4: Using the Library in a React App**

1. Install the Library**

npm install @sahilphondekar/react-component-library

2. Import CSS in Your Root Component

import "@sahilphondekar/react-component-library/dist/style.css";

3. Use the Button Component

import { Button } from '@sahilphondekar/react-component-library';

function App() {
return (
<Button variant="primary" size="large" onClick={() => alert('Clicked!')}>
Click Me
</Button>
);
}

Customization with CSS Variables

Override default styles in your app's CSS:

:root {
--primary-color: #ff6b6b;
--primary-hover: #ff5252;
--secondary-color: #f8f9fa;
}

Conclusion

You’ve now built a customizable React component library with:
Vite for fast builds
CSS Modules for scoped styling
npm publish for reusability

Extend it by adding more components (Card, Input, Modal) and themes! 🚀

Happy coding! 🎉