@

How to Create and Maintain UI React Components with Storybook

Learn how to efficiently build, and maintain reusable UI components in React using Storybook. This guide covers best practices for creating scalable components, visual testing, and enhancing development workflows.

Alim Naufal Photo Profile

Alim Naufal

Jul 07, 2025

How to Create and Maintain UI React Components with Storybook blog image

Why we use with Storybook

The article is based on my personal experience during the task where I had to research how to create and maintain react component for web development in the company I work for Systatum - a startup founded by a Harvard graduate - shoutout to our CEO, Adam N. Hakarsa.

We needed a tool that could help us preview and test each component, without running the entire app every time. It's a powerful tool that lets you build UI components in isolation. It made my workflow more efficient and allowed to:

  • Clearly visualize each component
  • Demonstrate how to use Storybook addons
  • Showcase customizable variants of components
  • Collaborate more effectively with other team members

Using Storybook helped us structure components better and save a lot of time during development and debugging, you can see our sample on this link:

Visit coneto.systatum.com to see our component.

Setup and basic usage

Installation

  1. You must install app w/ Storybook, If you want to start quickly, you can use this template: → npm create storybook@latest → you can choose app (next, react vite, etc)

  2. The project contains two folders: one for Storybook and one for the development frontend. For now, we’ll focus only on the Storybook setup.

  3. If you're using with Tailwind CSS, You need to configure Tailwind support in .storybook/preview

    import type { Preview } from "@storybook/react";
    import "../shared.css";
    
    const preview: Preview = {
      parameters: {
        controls: {
          matchers: {
            color: /(background|color)$/i,
            date: /Date$/i,
          },
        },
      },
    };
    
    export default preview;
    
  4. Install Tailwind CSS (React + Vite)

    Follow the official Tailwind + Vite installation steps:

    Click in this link

    Once installed, make sure to include Tailwind in your CSS:

    @import "tailwindcss";
    
  5. Setup PostCSS

    To enable Tailwind and other CSS tools, configure PostCSS in postcss.config.mjs:

    module.exports = {
    plugins: {
        "@tailwindcss/postcss": {},
        autoprefixer: {},
      },
    };
    
  6. Update Your package.json Scripts

    Make sure to define the scripts needed to run and build Storybook:

    {
     "name": "coneto",
     "version": "1.0.0",
     "type": "module",
     "private": true,
     "scripts": {
       "storybook": "storybook dev -p 6006",
       "build-storybook": "storybook build",
       "type-check": "tsc --noEmit",
       "lint": "eslint . --ext .js,.jsx,.ts,.tsx",
       "format": "prettier --write ."
     },
    ...
    }
    
  7. Run Storybook :

    To start Storybook, use one of the following depending on your package manager:

    `npm run storybook` OR `yarn storybook` OR `pnpm storybook`
    

Add your First Component Story

Let's say you want to create a button component, on folder components you must add button.tsx and button.stories.tsx

  1. Create your component file

    In the components/ folder, create a new file called button.tsx :

    // components/button.tsx
    import React from "react";
    
    export interface ButtonProps {
      label: string;
      variant?: "primary" | "secondary";
      onClick?: () => void;
    }
    
    export const Button: React.FC<ButtonProps> = ({
      label,
      variant = "primary",
      onClick,
    }) => {
      const styles = {
        primary: "bg-blue-500 text-white px-4 py-2 rounded",
        secondary: "bg-gray-300 text-black px-4 py-2 rounded",
      };
    
      return (
        <button className={styles[variant]} onClick={onClick}>
          {label}
        </button>
      );
    };
    
  2. Create your Storybook story

    In the same folder, add Button.stories.tsx :

    // components/button.stories.tsx
    import { Button } from "./Button";
    import type { Meta, StoryObj } from "@storybook/react";
    
    const meta: Meta<typeof Button> = {
      component: Button,
      title: "Controls/Button",
      tags: ["autodocs"],
    };
    
    export default meta;
    type Story = StoryObj<typeof Button>;
    
    export const Primary: Story = {
      args: {
        label: "Click Me",
        variant: "primary",
      },
    };
    
    export const Secondary: Story = {
      args: {
        label: "Cancel",
        variant: "secondary",
      },
    };
    

Maintaining Story Files

As your component library grows, maintaining stories becomes critical. Here are a few good practices:

  1. Use Meaningful Story Names

    Use clear, concise names like Primary , Disabled , WithIcon, etc., to represent real-world use cases.

  2. Group by functionality

    You can organize your stories into folders based on their functionality or title, such as: Controls/Button.

    Foldering your component
  3. Keep Stories Updated

    Whenever you change a component’s props or behavior, update the stories to reflect those changes. This avoids outdated previews and broken documentation.

  4. Use with useArgs() than useState() for state management.

    This is because the controls addon in Storybook allows live updates, so you can see the result directly in the UI. Here's an example about how to manage state using with useArgs() from @storybook/preview-api :

    const meta: Meta<typeof Togglebox> = {
      title: "Input Elements/Togglebox",
      component: Togglebox,
      tags: ["autodocs"],
      argTypes: {
        checked: {
          control: "boolean",
          description: "Whether the toggle is on",
          defaultValue: false,
        },
        isLoading: {
          control: "boolean",
          description: "Whether the toggle is in a loading state",
          defaultValue: false,
        },
        onChange: {
          action: "changed",
          description: "Callback when toggle is changed",
        },
        icon: {
          control: {
            type: "select",
          },
          options: Object.keys(RemixIcons),
          mapping: RemixIcons,
        },
        name: {
          table: { disable: true },
        },
      },
    };
    
    export default meta;
    
    type Story = StoryObj<typeof Togglebox>;
    
    export const Default: Story = {
      args: {
        checked: false,
      },
      render: (args) => {
        const [, setUpdateArgs] = useArgs();
    
        return (
          <Togglebox
            {...args}
            onChange={(e) => setUpdateArgs({ checked: e.target.checked })}
          />
        );
      },
    };
    

    And then the result can control and see like this:

  5. You can see progress on your way (Chromatic or Deploy or Staging Deployment)

    When you're working with UI components in Storybook, it's helpful to share your work visually — not just through code. Tools like Chromatic or staging deployments allow you to preview and track your progress clearly - not just through code. Tools like Chromatic or staging deployments` allow you to preview and track your progress more clearly.

    You can choose either option. For example:

    • Use a staging deployment (e.g., via Netlify) to share your Storybook build with others.
    • Use Chromatic to publish and review your components online.

    Chromatic is a web platform that works with Storybook. It lets you:

    • 📤 Publish your Storybook online — so others can see it without running it locally.
    • 👀 Preview changes before merging — useful for reviewing new or updated components.
    • 📸 Catch visual bugs — it shows visual differences between commits, helping you avoid design issues.
    • 🔗 Share a simple link — send it to your team for instant feedback.
    Team Collaboration on Component Modifications

    Visit chromatic.com to see documentation (how to used, config, etc.)

    That wraps up this article. I hope you found it meaningful and that it brings a positive impact to your team. Good luck, everyone!