<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Untitled Publication]]></title><description><![CDATA[Untitled Publication]]></description><link>https://ashutoshtiwari.hashnode.dev</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1711908725255/YlMtm8rwq.png</url><title>Untitled Publication</title><link>https://ashutoshtiwari.hashnode.dev</link></image><generator>RSS for Node</generator><lastBuildDate>Tue, 22 Sep 2026 12:44:52 GMT</lastBuildDate><atom:link href="https://ashutoshtiwari.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[How to Build a React UI Component Library: A Step-by-Step Guide using Shadcn UI, Vite, Tailwind CSS, and Storybook]]></title><description><![CDATA[Introduction
In this article, we will walk through the process of setting up a React UI component library using Shadcn UI, Vite, Tailwind CSS, and Storybook. But before we dive into the setup process, let’s understand what these technologies are and ...]]></description><link>https://ashutoshtiwari.hashnode.dev/how-to-build-react-ui-component-library-step-by-step-guide-shadcn-ui-vite-tailwind-css-storybook</link><guid isPermaLink="true">https://ashutoshtiwari.hashnode.dev/how-to-build-react-ui-component-library-step-by-step-guide-shadcn-ui-vite-tailwind-css-storybook</guid><category><![CDATA[React]]></category><category><![CDATA[UI]]></category><category><![CDATA[shadcn]]></category><category><![CDATA[vite]]></category><category><![CDATA[Tailwind CSS]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[TypeScript]]></category><category><![CDATA[Frontend Development]]></category><category><![CDATA[Storybook]]></category><category><![CDATA[CSS]]></category><category><![CDATA[Next.js]]></category><dc:creator><![CDATA[Ashutosh Tiwari]]></dc:creator><pubDate>Sun, 14 Apr 2024 19:39:42 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1713122967640/279003f8-8483-47dd-a942-6d49255ed0f1.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-introduction">Introduction</h2>
<p>In this article, we will walk through the process of setting up a React UI component library using Shadcn UI, Vite, Tailwind CSS, and Storybook. But before we dive into the setup process, let’s understand what these technologies are and why we are using them.  </p>
<ul>
<li><p><a target="_blank" href="https://ui.shadcn.com/"><strong>Shadcn UI:</strong></a> It is a collection of beautifully designed and accessible components that you can use in your apps. It’s not a traditional component library that you install as a dependency. Instead, you can browse, copy, and paste the components, or customize them to suit your needs. We are using Shadcn UI because it allows us to quickly prototype and build components with a consistent design system.</p>
</li>
<li><p><a target="_blank" href="https://vitejs.dev/guide/"><strong>Vite</strong></a><strong>:</strong> Vite (French word for “quick”, pronounced /vit/, like “veet”) is a build tool that aims to provide a faster and leaner development experience for modern web projects. It consists of two major parts: A dev server that provides rich feature enhancements over native ES modules, for example extremely fast Hot Module Replacement (HMR), and a build command that bundles your code with Rollup, pre-configured to output highly optimized static assets for production. We are using Vite because it offers a faster and more efficient build process compared to traditional tools.</p>
</li>
<li><p><a target="_blank" href="https://tailwindcss.com/"><strong>Tailwind CSS</strong></a>: Tailwind CSS is a utility-first CSS framework for rapidly building custom user interfaces. It provides low-level utility classes that let you build completely custom designs without ever leaving your HTML. It does not provide a series of predefined classes for elements such as buttons or tables. We are using Tailwind CSS because it gives us the flexibility to create custom styles easily and efficiently.</p>
</li>
<li><p><a target="_blank" href="https://storybook.js.org/"><strong>Storybook</strong></a>: Storybook is a tool for building UI components and pages in isolation. It helps you develop and share hard-to-reach states and edge cases without needing to run your whole app. Thousands of teams use it for UI development, testing, and documentation. We are using Storybook because it allows us to develop and test our components in isolation, making the development process more efficient and manageable.</p>
</li>
</ul>
<p>Now that we have a better understanding of these technologies, let’s dive into the setup process.</p>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>Before we start, I assume you already know the following:</p>
<ul>
<li><p>React</p>
</li>
<li><p>TypeScript</p>
</li>
<li><p>Tailwind CSS</p>
</li>
</ul>
<p>And make sure you have the following installed on your system:</p>
<ul>
<li><strong>Node.js</strong> and <strong>npm</strong></li>
</ul>
<h2 id="heading-step-1-setting-up-the-project-with-vite">Step 1: Setting up the Project with Vite</h2>
<p>First, we need to set up a new project using Vite (5.2.0). Run the following command in your terminal:</p>
<pre><code class="lang-bash">npm create vite@latest
</code></pre>
<p>Follow the on-screen prompts in the terminal and give your project name. For the purpose of this article we are using the name "ui-library". Since we will be using React and TypeScript, select the options accordingly.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1713117235833/a2d331c4-af7f-486f-b41c-5b09b9b25d42.png" alt class="image--center mx-auto" /></p>
<p>After following all the instructions, you should be inside the ui-library project directory and be able to see the Vite demo page at <a target="_blank" href="http://localhost:5173/">http://localhost:5173/</a>.</p>
<h2 id="heading-step-2-installing-tailwind-css">Step 2: Installing Tailwind CSS</h2>
<p>Next, we install Tailwind CSS (3.4.3) using the following command:</p>
<pre><code class="lang-bash">npm install -D tailwindcss postcss autoprefixer
</code></pre>
<h2 id="heading-step-3-configuring-tailwind-css">Step 3: Configuring Tailwind CSS</h2>
<p>After installing Tailwind CSS, we need to create a configuration file:</p>
<pre><code class="lang-bash">npx tailwindcss init -p
</code></pre>
<p>This will create a <code>tailwind.config.js</code> file in your project root. Update the file as below for now for testing, since it will be get updated once we have shadcn installed:  </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1713118352095/0d4efdd8-3833-4b1d-8f42-f8e8316982a4.png" alt class="image--center mx-auto" /></p>
<p>Add the <code>@tailwind</code> directives for each of Tailwind’s layers to your <code>src/index.css</code> file:  </p>
<pre><code class="lang-css"><span class="hljs-keyword">@tailwind</span> base;
<span class="hljs-keyword">@tailwind</span> components;
<span class="hljs-keyword">@tailwind</span> utilities;
</code></pre>
<p>Replace everything in your <code>App.tsx</code> file with the following and run <code>npm run dev</code>:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> &lt;h1 className=<span class="hljs-string">'text-3xl font-bold underline'</span>&gt;Hello world!&lt;/h1&gt;
}
</code></pre>
<p>You should see the following in the browser now:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1713118769414/782cafb2-74a3-4ad9-9a90-5cd7d13fa2b7.png" alt class="image--center mx-auto" /></p>
<p>At this point, we have a project with Vite and Tailwind installed.</p>
<h2 id="heading-step-4-integrating-storybook">Step 4: Integrating Storybook</h2>
<p>Now we will be integrating Storybook 8 to develop our UI components in isolation and provide a clean documentation for each of those components. Install it using the following command:</p>
<pre><code class="lang-bash">npx storybook@latest init
</code></pre>
<p>This command will automatically detect your project type and add the necessary dependencies and scripts to your <code>package.json</code> and you will see the below demo page at <a target="_blank" href="http://localhost:6006/?path=/story/example-button--primary&amp;onboarding=true">http://localhost:6006/</a>:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1713119359111/6247c650-24a7-4307-b05b-3d5318eee109.png" alt class="image--center mx-auto" /></p>
<p>For Tailwind classes to work with Storybook, we need to import it in the <code>.storybook/preview.ts</code> file:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> <span class="hljs-string">'tailwindcss/tailwind.css'</span>
</code></pre>
<h2 id="heading-step-5-installing-shadcn-ui">Step 5: Installing Shadcn UI</h2>
<p>Now we will be setting up Shadcn in our project, using which we will be creating our UI components.</p>
<p>Firstly, we need to add some code in <code>compilerOptions</code> of our <code>tsconfig.json</code> file to resolve paths:  </p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"compilerOptions"</span>: {
    <span class="hljs-comment">// ...</span>
    <span class="hljs-attr">"baseUrl"</span>: <span class="hljs-string">"."</span>,
    <span class="hljs-attr">"paths"</span>: {
      <span class="hljs-attr">"@/*"</span>: [
        <span class="hljs-string">"./src/*"</span>
      ]
    }
    <span class="hljs-comment">// ...</span>
  }
}
</code></pre>
<p>Then we will install <code>@types/node</code> using the following command:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># (so you can import "path" without error)</span>
npm i -D @types/node
</code></pre>
<p>Add the following code to the <code>vite.config.ts</code> so your app can resolve paths without error:</p>
<pre><code class="lang-typescript">
<span class="hljs-keyword">import</span> path <span class="hljs-keyword">from</span> <span class="hljs-string">"path"</span>
<span class="hljs-keyword">import</span> react <span class="hljs-keyword">from</span> <span class="hljs-string">"@vitejs/plugin-react"</span>
<span class="hljs-keyword">import</span> { defineConfig } <span class="hljs-keyword">from</span> <span class="hljs-string">"vite"</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> defineConfig({
  plugins: [react()],
  resolve: {
    alias: {
      <span class="hljs-string">"@"</span>: path.resolve(__dirname, <span class="hljs-string">"./src"</span>),
    },
  },
})
</code></pre>
<p>Run the <code>shadcn-ui</code> init command to setup your project:</p>
<pre><code class="lang-bash">npx shadcn-ui@latest init
</code></pre>
<p>Choose the options as follows:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1713120552171/a4ee30ef-c67d-443d-9967-70f6e9fef999.png" alt class="image--center mx-auto" /></p>
<p>Now we are ready to add our first component.</p>
<h2 id="heading-step-6-creating-a-component">Step 6: Creating a Component</h2>
<p>Now, let’s create a simple component using Shadcn UI. The command below will add the <code>Button</code> component to your project:</p>
<pre><code class="lang-bash">npx shadcn-ui@latest add button
</code></pre>
<p>You can now import the Button component in your Storybook story or edit the component at <code>src\components\ui\button.tsx</code></p>
<h2 id="heading-step-7-adding-component-to-storybook">Step 7: Adding Component to Storybook</h2>
<p>Finally, let’s add our <code>Button</code> component to Storybook. There will be an existing Button component created by Storybook, we can delete it along with other sample components. Edit file <code>Button.stories.tsx</code> in the <code>src\stories\Button.stories.ts</code> directory as follows:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { Button } <span class="hljs-keyword">from</span> <span class="hljs-string">'@/components/ui/button'</span>
<span class="hljs-keyword">import</span> <span class="hljs-keyword">type</span> { Meta, StoryObj } <span class="hljs-keyword">from</span> <span class="hljs-string">'@storybook/react'</span>
<span class="hljs-keyword">import</span> { fn } <span class="hljs-keyword">from</span> <span class="hljs-string">'@storybook/test'</span>

<span class="hljs-keyword">const</span> meta = {
  title: <span class="hljs-string">'Example/Button'</span>,
  component: Button,
  parameters: {
    layout: <span class="hljs-string">'centered'</span>,
  },
  tags: [<span class="hljs-string">'autodocs'</span>],
  argTypes: {},
  args: { onClick: fn() },
} satisfies Meta&lt;<span class="hljs-keyword">typeof</span> Button&gt;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> meta
<span class="hljs-keyword">type</span> Story = StoryObj&lt;<span class="hljs-keyword">typeof</span> meta&gt;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> Primary: Story = {
  args: {
    children: <span class="hljs-string">'Button'</span>,
  },
}
</code></pre>
<p>Now, you can run <code>npm run storybook</code> to start Storybook, and see your component in action at <a target="_blank" href="http://localhost:6006/">http://localhost:6006/</a>. It should look something like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1713121322543/158d26aa-3e00-4ec0-a346-0f4418e2c80f.png" alt class="image--center mx-auto" /></p>
<p>You can now go ahead and customize your Button component and add more shadcn components from <a target="_blank" href="https://ui.shadcn.com/docs/components">here</a>.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Congratulations! You’ve just set up a React UI component library using Shadcn UI, Vite, Tailwind CSS, and Storybook. This setup will help you create and manage your components efficiently.  </p>
<p>Do give a like if it helped you and any feedback is appreciated :)</p>
]]></content:encoded></item></channel></rss>