Creating a custom UI library using React+Vite and Storybook

  

Crafting a Reusable UI Component Library with React and Storybook


In the dynamic world of web development, building reusable UI component libraries is a strategic move that promotes consistency, scalability, and efficient development.

A design system serves as the foundational blueprint for consistency, efficiency, and collaboration within a development team. In the dynamic landscape of software development, where teams collaborate on complex projects, a design system becomes an essential tool for success. Firstly, it establishes a unified visual language, ensuring that every team member interprets and implements design elements consistently. This consistency is crucial for building a seamless and polished user experience across various components and screens.

Secondly, a design system accelerates the development process. By encapsulating reusable components, patterns, and guidelines, teams can streamline their workflow, reducing redundancy and development time. This efficiency not only facilitates faster project delivery but also enhances maintainability as updates and modifications can be made cohesively across the entire system.

Moreover, a design system fosters collaboration and communication among team members. With a shared set of design principles and components, designers, developers, and product managers can work in tandem, reducing misunderstandings and ensuring a unified vision. This collaborative approach leads to better decision-making and a more cohesive end product.

In addition, a design system serves as a living document that evolves alongside the project. As the application grows and adapts to changing requirements, the design system becomes a central repository for knowledge, ensuring that the team has a comprehensive reference for design patterns, best practices, and accessibility guidelines. This adaptability is crucial for scalability and long-term project success.

In summary, a design system is a powerful tool that brings cohesion, efficiency, and collaboration to a development team. It is not just a set of guidelines; it is a dynamic framework that empowers teams to deliver high-quality, consistent, and user-friendly products in a rapidly evolving technological landscape.


In this blog post, we'll dive into the creation of a customizable and interactive button component using React and Storybook. The code provided showcases a Button component with various variants, and we'll explore how Storybook facilitates the development and testing of these components within the context of building a reusable UI library.

The Reusable Button Component

Let's start by examining the Button component



  • The buttonStyles constant is created using cva, defining a set of base styles and variants for the button.
  • Base styles include width (w-100), rounded corners (rounded-md), font weight (font-semibold), focus outline removal (focus:outline-none), and cursor behavior for disabled state (disabled:cursor-not-allowed).
  • Variants are defined for variant, size, and colorscheme. Variants can be "solid," "outline," or "ghost," sizes can be "sm," "md," or "lg," and color schemes can include different color configurations.
  • compoundVariants specify combinations of variants, each with its own set of class names. For example, a solid button with a primary color scheme has a specific background and hover styles.
  • defaultVariants set the default values for the variant, size, and colorscheme to "solid," "md," and "primary," respectively.

  • The Button component receives props such as variant, size, colorScheme, className, btn_name, and onClick. These props allow customization of the button's appearance and behavior. The buttonStyles function from CVA is used to generate the class names based on the provided props. The cn function is used to combine the generated class names with any additional class names passed through the className prop. The forwardRef function enables the component to forward its ref to the underlying button element. The button element has an onClick event handler that triggers the function passed through the onClick prop.

Storybook Integration for UI Library Development

After creating the above component lets now implement storybook in our project.

Open a terminal in the project directory and run the below command.
npx storybook init

This command will generate example storybook stories which can be safely deleted as we are going to implement story for the above component.

Coming to the implementation of the above component in storybook stories to showcase the UI to many stakeholders such as developers, customers etc. Storybook enables to creation of an isolated environment to separately test the UI components. In this project I have used a storybook to show how the button component behaves and how many variants it has.


create a seperate file with name button.stories.jsx under the same component folder and copy the below code.

import Button from './index';
import { action } from '@storybook/addon-actions';

export default {
component: Button,
title: 'Components/Button',
tags: ['autodocs'],
parameters: {
layout: "centered",
},
argTypes: {
variant: {
options: ['solid', 'outline', 'ghost'],
control: { type: 'radio' },
},
}
};
export const Default = {
args: {
btn_name: "Click me",
variant: "solid",
size: "md",
onClick: action('Default button clicked'),
},
};

export const Outline = {
args: {
variant: "outline",
size: "sm",
btn_name: "Click me",
onClick: action('Outline button clicked'),
},
};

export const Ghost = {
args: {
variant: "ghost",
size: "sm",
btn_name: "Click me",
onClick: action('Ghost button clicked'),
},
};

This code sets the stage for a Button component with different variants, each represented by a Storybook story. The argTypes section enables interactive controls, allowing developers to easily switch between button variants.





The Button component has variants Default(Solid), Outlined and Ghost. Users can directly use the library after downloading it from npm site.


Storybook not only provides an environment to test the UI components in isolation but also it enables developers/users to understand the documentation and how the component behaves. Various tabs in storybook such controls, actions can be used to understand the behaviour of the component.



Let's explore how Storybook enhances the process of building a reusable UI library:

  • Component Documentation: The title and tags fields in the Storybook configuration provide essential documentation for the Button component. Tags like 'autodocs' hint to Storybook that it should generate documentation automatically.

  • Interactive Controls: With the argTypes section, developers can interactively control the variant prop, providing a visual representation of different button styles. This feature is particularly valuable when building a UI library where customization is key.

  • Story Variants: Each story (e.g., Default, Outline, and Ghost) acts as a showcase for a specific variant of the button. Developers can easily visualize and test different button configurations within the Storybook UI.

Making Buttons Interactive

The Button component is not just a static element; it's designed to be interactive. The onClick prop is configured using Storybook's action addon, allowing developers to observe and interact with the button's click behavior directly within the Storybook UI



We are finally done making the component library. You must be wondering how this library can be used by other members?


Now let us see how we can build the deployable library using vite.


In vite.config.js file make the below changes

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

// https://vitejs.dev/config/
export default defineConfig({
resolve: {
alias: {
'@': path.resolve(__dirname, './src'),
}
},
build: {
lib: {
entry: path.resolve(__dirname, './src/components/index.jsx'),
name: 'AshimsUI',
fileName: 'ashims-ui-lib'
},
rollupOptions: {
external: ['react', 'react-dom'],
output: {
globals: {
react: "React",
"react-dom": "ReactDOM",
}
}
}
},
plugins: [react()],
})


Now modify and the below line in the package.json file. After making changes run npm run build in the terminal. this will generate dist files which can be hosted in the npm site.


"type": "module",
"files": [
"dist"
],
"main": "dist/ui-component-library-umd.cjs",
"module": "dist/ui-component-library.js",
"exports": {
"." :{
"import": "./dist/ui-component-library.js",
"require": "./dist/ui-component-library-umd.cjs"
}
},





We are now finally ready to deploy the lib files in the npm site. Thank you!

Comments