<?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[Chetan Verma]]></title><description><![CDATA[I have delivered world-class user experiences to millions of people. Well-versed with React,
Javascript, and most of the Web frameworks.]]></description><link>https://blog.chetanverma.com</link><generator>RSS for Node</generator><lastBuildDate>Mon, 18 May 2026 03:18:33 GMT</lastBuildDate><atom:link href="https://blog.chetanverma.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[How to create an awesome Kanban board using dnd-kit]]></title><description><![CDATA[https://youtu.be/IZ3w2PNh-hE
 
Introduction
Hey everyone, we will create an awesome Kanban board using dnd-kit in this post.
We will use the next.js starter with tailwindcss as a code starter for our Kanban board.
prerequisite -

containers : a conta...]]></description><link>https://blog.chetanverma.com/how-to-create-an-awesome-kanban-board-using-dnd-kit</link><guid isPermaLink="true">https://blog.chetanverma.com/how-to-create-an-awesome-kanban-board-using-dnd-kit</guid><category><![CDATA[React]]></category><category><![CDATA[kanban]]></category><category><![CDATA[Next.js]]></category><category><![CDATA[Tailwind CSS]]></category><category><![CDATA[dndkit]]></category><dc:creator><![CDATA[Chetan verma]]></dc:creator><pubDate>Tue, 08 Aug 2023 09:35:03 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1691476345732/49e7a8c2-ab59-4734-b2b7-75e4066013dc.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/IZ3w2PNh-hE">https://youtu.be/IZ3w2PNh-hE</a></div>
<p> </p>
<h3 id="heading-introduction">Introduction</h3>
<p>Hey everyone, we will create an awesome Kanban board using <code>dnd-kit</code> in this post.</p>
<p>We will use the next.js starter with tailwindcss as a code starter for our Kanban board.</p>
<p><strong>prerequisite -</strong></p>
<ul>
<li><p><code>containers</code> : a container is a board of Kanban board that will contain the Items or tasks of the Kanban board</p>
</li>
<li><p><code>Items</code> : these are the items that will be dragged between the containers or board of Kanban.</p>
</li>
</ul>
<p>so, let's get started with our app</p>
<p>In your terminal run these commands and install tailwindcss -</p>
<pre><code class="lang-bash">npx create-next-app my-project
<span class="hljs-built_in">cd</span> my-project
</code></pre>
<h3 id="heading-install-dnd-kit">Install <code>dnd-kit</code></h3>
<p>once we have our nextjs starter with tailwindcss ready we are going to install the following packages.</p>
<ul>
<li><p><code>@dnd-kit/core</code> : this is the core library for handling our sorting and dragging.</p>
</li>
<li><p><code>@dndkit-sortable</code> : this package is the extension to the <code>dnd-kit</code> which will help us in sorting the <code>containers</code> and <code>items</code></p>
</li>
<li><p><code>uuid</code>: this library is going to handle our unique ID generation.</p>
</li>
</ul>
<p>okay so now we have all the packages that we need installed in our app.</p>
<h3 id="heading-layout-setup">Layout setup-</h3>
<p>Now, let's set up our base setup where we will be adding our Kanban board.</p>
<p><code>pages/index.tsx</code> -</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> { v4 <span class="hljs-keyword">as</span> uuidv4 } <span class="hljs-keyword">from</span> <span class="hljs-string">'uuid'</span>;

<span class="hljs-comment">// DnD</span>
<span class="hljs-keyword">import</span> {
  DndContext,
  DragEndEvent,
  DragMoveEvent,
  DragOverlay,
  DragStartEvent,
  KeyboardSensor,
  PointerSensor,
  UniqueIdentifier,
  closestCorners,
  useSensor,
  useSensors,
} <span class="hljs-keyword">from</span> <span class="hljs-string">'@dnd-kit/core'</span>;
<span class="hljs-keyword">import</span> {
  SortableContext,
  arrayMove,
  sortableKeyboardCoordinates,
} <span class="hljs-keyword">from</span> <span class="hljs-string">'@dnd-kit/sortable'</span>;

<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">Home</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"mx-auto max-w-7xl py-10"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex items-center justify-between gap-y-2"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-gray-800 text-3xl font-bold"</span>&gt;</span>Dnd-kit Guide<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"mt-10"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"grid grid-cols-3 gap-6"</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>After adding our base layout we will have something like this on the screen -</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1691400455641/0710981e-1d91-4d17-8ca4-6aa5bd37fd90.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-state-and-types-setup">State and types setup</h3>
<p>Okay, so the next thing that we need to do is to add all the states that we need in the app and also define the type for our <code>containers</code></p>
<p><code>DnDType (Container / Board Type)</code> :</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { UniqueIdentifier } <span class="hljs-keyword">from</span> <span class="hljs-string">'@dnd-kit/core'</span>;

type DNDType = {
  <span class="hljs-attr">id</span>: UniqueIdentifier; <span class="hljs-comment">// Unique Id for Containers</span>
  title: string;
  items: {
    <span class="hljs-attr">id</span>: UniqueIdentifier; <span class="hljs-comment">// Unique Id for Items</span>
    title: string;
  }[];
};
</code></pre>
<p>we have the type of our <code>container</code> which is going to hold all of our items of the kanban board.</p>
<p>now let's define the react states that we need in the app.</p>
<pre><code class="lang-javascript">  <span class="hljs-keyword">const</span> [containers, setContainers] = useState&lt;DNDType[]&gt;([]);
  <span class="hljs-keyword">const</span> [activeId, setActiveId] = useState&lt;UniqueIdentifier | <span class="hljs-literal">null</span>&gt;(<span class="hljs-literal">null</span>);
  <span class="hljs-keyword">const</span> [currentContainerId, setCurrentContainerId] =
    useState&lt;UniqueIdentifier&gt;();
  <span class="hljs-keyword">const</span> [containerName, setContainerName] = useState(<span class="hljs-string">''</span>);
  <span class="hljs-keyword">const</span> [itemName, setItemName] = useState(<span class="hljs-string">''</span>);
  <span class="hljs-keyword">const</span> [showAddContainerModal, setShowAddContainerModal] = useState(<span class="hljs-literal">false</span>);
  <span class="hljs-keyword">const</span> [showAddItemModal, setShowAddItemModal] = useState(<span class="hljs-literal">false</span>);
</code></pre>
<ul>
<li><p><code>containers</code> - This state will keep track of all the containers that we are going to add to the Kanban board with items inside it.</p>
</li>
<li><p><code>activeId</code> - It is going to be used to track the current selected or dragging element Id, which we will use later when we are rendering <code>DragOverlay</code></p>
</li>
<li><p><code>currentContainerId</code> - We are going to use this container ID when we are adding a new Item to a container.</p>
</li>
<li><p><code>itemName</code> &amp; <code>containerName</code> - these states will be used in our controlled Input which will give us the name of the container and item that we are going to create.</p>
</li>
<li><p><code>showAddContainerModal</code> &amp; <code>showAddItemModal</code> - these states will be used to render the modal of container and item.</p>
</li>
</ul>
<h3 id="heading-dndcontext-setup">DndContext Setup -</h3>
<p>Okay so now let's add DndContext to our app which will hold all of our SortableContext.</p>
<p><code>DndContext</code> : In order for your <strong><em>Droppable</em></strong> and <strong><em>Draggable</em></strong> components to interact with each other, you'll need to make sure that the part of your React tree that uses them is nested within a parent <code>&lt;DndContext&gt;</code> component. The <code>&lt;DndContext&gt;</code> provider makes use of the <a target="_blank" href="https://legacy.reactjs.org/docs/context.html">React Context API</a> to share data between draggable and droppable components and hooks.</p>
<p><code>SortableContext</code> : The <code>SortableContext</code> provides information via context that is consumed by the <a target="_blank" href="/presets/sortable/usesortable"><code>useSortable</code></a> hook</p>
<p>So now that we know what the use of these react components let's add those to our app.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> { v4 <span class="hljs-keyword">as</span> uuidv4 } <span class="hljs-keyword">from</span> <span class="hljs-string">'uuid'</span>;

<span class="hljs-comment">// DnD</span>
<span class="hljs-keyword">import</span> {
  DndContext,
  DragEndEvent,
  DragMoveEvent,
  DragOverlay,
  DragStartEvent,
  KeyboardSensor,
  PointerSensor,
  UniqueIdentifier,
  closestCorners,
  useSensor,
  useSensors,
} <span class="hljs-keyword">from</span> <span class="hljs-string">'@dnd-kit/core'</span>;
<span class="hljs-keyword">import</span> {
  SortableContext,
  arrayMove,
  sortableKeyboardCoordinates,
} <span class="hljs-keyword">from</span> <span class="hljs-string">'@dnd-kit/sortable'</span>;
<span class="hljs-keyword">import</span> Container <span class="hljs-keyword">from</span> <span class="hljs-string">'@/components/Container'</span>;
<span class="hljs-keyword">import</span> Items <span class="hljs-keyword">from</span> <span class="hljs-string">'@/components/Item'</span>;

<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">Home</span>(<span class="hljs-params"></span>) </span>{
  type DNDType = {
    <span class="hljs-attr">id</span>: UniqueIdentifier; <span class="hljs-comment">// Unique Id for Containers</span>
    title: string;
    items: {
      <span class="hljs-attr">id</span>: UniqueIdentifier; <span class="hljs-comment">// Unique Id for Items</span>
      title: string;
    }[];
  };

  <span class="hljs-keyword">const</span> [containers, setContainers] = useState&lt;DNDType[]&gt;([]);
  <span class="hljs-keyword">const</span> [activeId, setActiveId] = useState&lt;UniqueIdentifier | <span class="hljs-literal">null</span>&gt;(<span class="hljs-literal">null</span>);
  <span class="hljs-keyword">const</span> [currentContainerId, setCurrentContainerId] =
    useState&lt;UniqueIdentifier&gt;();
  <span class="hljs-keyword">const</span> [containerName, setContainerName] = useState(<span class="hljs-string">''</span>);
  <span class="hljs-keyword">const</span> [itemName, setItemName] = useState(<span class="hljs-string">''</span>);
  <span class="hljs-keyword">const</span> [showAddContainerModal, setShowAddContainerModal] = useState(<span class="hljs-literal">false</span>);
  <span class="hljs-comment">// Dnd Handlers</span>
  <span class="hljs-keyword">const</span> sensors = useSensors(
    useSensor(PointerSensor),
    useSensor(KeyboardSensor, {
      <span class="hljs-attr">coordinateGetter</span>: sortableKeyboardCoordinates,
    }),
  );

  <span class="hljs-keyword">const</span> handleDragStart = <span class="hljs-function">(<span class="hljs-params">event: DragStartEvent</span>) =&gt;</span> {};
  <span class="hljs-keyword">const</span> handleDragMove = <span class="hljs-function">(<span class="hljs-params">event: DragMoveEvent</span>) =&gt;</span> {};
  <span class="hljs-keyword">const</span> handleDragEnd = <span class="hljs-function">(<span class="hljs-params">event: DragEndEvent</span>) =&gt;</span> {};
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"mx-auto max-w-7xl py-10"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex items-center justify-between gap-y-2"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-gray-800 text-3xl font-bold"</span>&gt;</span>Dnd-kit Guide<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"mt-10"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"grid grid-cols-3 gap-6"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">DndContext</span>
            <span class="hljs-attr">sensors</span>=<span class="hljs-string">{sensors}</span>
            <span class="hljs-attr">collisionDetection</span>=<span class="hljs-string">{closestCorners}</span>
            <span class="hljs-attr">onDragStart</span>=<span class="hljs-string">{handleDragStart}</span>
            <span class="hljs-attr">onDragMove</span>=<span class="hljs-string">{handleDragMove}</span>
            <span class="hljs-attr">onDragEnd</span>=<span class="hljs-string">{handleDragEnd}</span>
          &gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">SortableContext</span> <span class="hljs-attr">items</span>=<span class="hljs-string">{containers.map((i)</span> =&gt;</span> i.id)}&gt;
              {containers.map((container) =&gt; (
                <span class="hljs-tag">&lt;<span class="hljs-name">Container</span>
                  <span class="hljs-attr">id</span>=<span class="hljs-string">{container.id}</span>
                  <span class="hljs-attr">title</span>=<span class="hljs-string">{container.title}</span>
                  <span class="hljs-attr">key</span>=<span class="hljs-string">{container.id}</span>
                  <span class="hljs-attr">onAddItem</span>=<span class="hljs-string">{()</span> =&gt;</span> {}}
                &gt;
                  <span class="hljs-tag">&lt;<span class="hljs-name">SortableContext</span> <span class="hljs-attr">items</span>=<span class="hljs-string">{container.items.map((i)</span> =&gt;</span> i.id)}&gt;
                    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex items-start flex-col gap-y-4"</span>&gt;</span>
                      {container.items.map((i) =&gt; (
                        <span class="hljs-tag">&lt;<span class="hljs-name">Items</span> <span class="hljs-attr">title</span>=<span class="hljs-string">{i.title}</span> <span class="hljs-attr">id</span>=<span class="hljs-string">{i.id}</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{i.id}</span> /&gt;</span>
                      ))}
                    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
                  <span class="hljs-tag">&lt;/<span class="hljs-name">SortableContext</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">Container</span>&gt;</span>
              ))}
            <span class="hljs-tag">&lt;/<span class="hljs-name">SortableContext</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">DndContext</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<h3 id="heading-container">Container -</h3>
<p>We are going to <code>useSortable</code> hook, which will give us <code>attributes</code>, <code>setNodeRef</code>, <code>listerners</code>, <code>transform</code>, <code>transition</code> , <code>isDragging</code> which we will use these properties in our component to make the component behave like a draggable and droppable element.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> ContainerProps <span class="hljs-keyword">from</span> <span class="hljs-string">'./container.type'</span>;
<span class="hljs-keyword">import</span> { useSortable } <span class="hljs-keyword">from</span> <span class="hljs-string">'@dnd-kit/sortable'</span>;
<span class="hljs-keyword">import</span> { CSS } <span class="hljs-keyword">from</span> <span class="hljs-string">'@dnd-kit/utilities'</span>;
<span class="hljs-keyword">import</span> clsx <span class="hljs-keyword">from</span> <span class="hljs-string">'clsx'</span>;
<span class="hljs-keyword">import</span> { Button } <span class="hljs-keyword">from</span> <span class="hljs-string">'../Button'</span>;

<span class="hljs-keyword">const</span> Container = <span class="hljs-function">(<span class="hljs-params">{
  id,
  children,
  title,
  description,
  onAddItem,
}: ContainerProps</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> {
    attributes,
    setNodeRef,
    listeners,
    transform,
    transition,
    isDragging,
  } = useSortable({
    <span class="hljs-attr">id</span>: id,
    <span class="hljs-attr">data</span>: {
      <span class="hljs-attr">type</span>: <span class="hljs-string">'container'</span>,
    },
  });
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>
      {<span class="hljs-attr">...attributes</span>}
      <span class="hljs-attr">ref</span>=<span class="hljs-string">{setNodeRef}</span>
      <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span>
        <span class="hljs-attr">transition</span>,
        <span class="hljs-attr">transform:</span> <span class="hljs-attr">CSS.Translate.toString</span>(<span class="hljs-attr">transform</span>),
      }}
      <span class="hljs-attr">className</span>=<span class="hljs-string">{clsx(</span>
        '<span class="hljs-attr">w-full</span> <span class="hljs-attr">h-full</span> <span class="hljs-attr">p-4</span> <span class="hljs-attr">bg-gray-50</span> <span class="hljs-attr">rounded-xl</span> <span class="hljs-attr">flex</span> <span class="hljs-attr">flex-col</span> <span class="hljs-attr">gap-y-4</span>',
        <span class="hljs-attr">isDragging</span> &amp;&amp; '<span class="hljs-attr">opacity-50</span>',
      )}
    &gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex items-center justify-between"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex flex-col gap-y-1"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-gray-800 text-xl"</span>&gt;</span>{title}<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-gray-400 text-sm"</span>&gt;</span>{description}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
          <span class="hljs-attr">className</span>=<span class="hljs-string">"border p-2 text-xs rounded-xl shadow-lg hover:shadow-xl"</span>
          {<span class="hljs-attr">...listeners</span>}
        &gt;</span>
          Drag Handle
        <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

      {children}
      <span class="hljs-tag">&lt;<span class="hljs-name">Button</span> <span class="hljs-attr">variant</span>=<span class="hljs-string">"ghost"</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{onAddItem}</span>&gt;</span>
        Add Item
      <span class="hljs-tag">&lt;/<span class="hljs-name">Button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Container;
</code></pre>
<h3 id="heading-item">Item-</h3>
<p>It will be similar to a container that we will be using <code>useSortable</code> because we are going to drag and drop these in the container or board.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { UniqueIdentifier } <span class="hljs-keyword">from</span> <span class="hljs-string">'@dnd-kit/core'</span>;
<span class="hljs-keyword">import</span> { useSortable } <span class="hljs-keyword">from</span> <span class="hljs-string">'@dnd-kit/sortable'</span>;
<span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> { CSS } <span class="hljs-keyword">from</span> <span class="hljs-string">'@dnd-kit/utilities'</span>;
<span class="hljs-keyword">import</span> clsx <span class="hljs-keyword">from</span> <span class="hljs-string">'clsx'</span>;

type ItemsType = {
  <span class="hljs-attr">id</span>: UniqueIdentifier;
  title: string;
};

<span class="hljs-keyword">const</span> Items = <span class="hljs-function">(<span class="hljs-params">{ id, title }: ItemsType</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> {
    attributes,
    listeners,
    setNodeRef,
    transform,
    transition,
    isDragging,
  } = useSortable({
    <span class="hljs-attr">id</span>: id,
    <span class="hljs-attr">data</span>: {
      <span class="hljs-attr">type</span>: <span class="hljs-string">'item'</span>,
    },
  });
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>
      <span class="hljs-attr">ref</span>=<span class="hljs-string">{setNodeRef}</span>
      {<span class="hljs-attr">...attributes</span>}
      <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span>
        <span class="hljs-attr">transition</span>,
        <span class="hljs-attr">transform:</span> <span class="hljs-attr">CSS.Translate.toString</span>(<span class="hljs-attr">transform</span>),
      }}
      <span class="hljs-attr">className</span>=<span class="hljs-string">{clsx(</span>
        '<span class="hljs-attr">px-2</span> <span class="hljs-attr">py-4</span> <span class="hljs-attr">bg-white</span> <span class="hljs-attr">shadow-md</span> <span class="hljs-attr">rounded-xl</span> <span class="hljs-attr">w-full</span> <span class="hljs-attr">border</span> <span class="hljs-attr">border-transparent</span> <span class="hljs-attr">hover:border-gray-200</span> <span class="hljs-attr">cursor-pointer</span>',
        <span class="hljs-attr">isDragging</span> &amp;&amp; '<span class="hljs-attr">opacity-50</span>',
      )}
    &gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex items-center justify-between"</span>&gt;</span>
        {title}
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
          <span class="hljs-attr">className</span>=<span class="hljs-string">"border p-2 text-xs rounded-xl shadow-lg hover:shadow-xl"</span>
          {<span class="hljs-attr">...listeners</span>}
        &gt;</span>
          Drag Handle
        <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Items;
</code></pre>
<p>Ok so now we have all the things that we need ready for sorting,</p>
<p>let's implement the <code>DndContext</code> handlers to bring our kanban board to life.</p>
<h3 id="heading-handle-drag-start">Handle Drag Start-</h3>
<p>In this function, we are going to extract the active element and then set the active ID state.</p>
<pre><code class="lang-javascript">  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">handleDragStart</span>(<span class="hljs-params">event: DragStartEvent</span>) </span>{
    <span class="hljs-keyword">const</span> { active } = event;
    <span class="hljs-keyword">const</span> { id } = active;
    setActiveId(id);
  }
</code></pre>
<h3 id="heading-handle-drag-move">Handle Drag Move -</h3>
<ul>
<li><p>In this, we are going to extract the active and over <code>item</code> from the event.</p>
</li>
<li><p>there are going to be two types of scenarios we need to handle</p>
<ul>
<li><p><strong>Sorting between Items</strong> - In this, we are going to handle the sorting between the items and check both the <code>active</code> and <code>over</code> element are items and then swap those items to their respective positions.</p>
</li>
<li><p><strong>Sorting between active Item and over container -</strong> when we have the active element to be an Item we are dragging that over an empty container.</p>
</li>
</ul>
</li>
</ul>
<pre><code class="lang-javascript">

  <span class="hljs-keyword">const</span> handleDragMove = <span class="hljs-function">(<span class="hljs-params">event: DragMoveEvent</span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> { active, over } = event;

    <span class="hljs-comment">// Handle Items Sorting</span>
    <span class="hljs-keyword">if</span> (
      active.id.toString().includes(<span class="hljs-string">'item'</span>) &amp;&amp;
      over?.id.toString().includes(<span class="hljs-string">'item'</span>) &amp;&amp;
      active &amp;&amp;
      over &amp;&amp;
      active.id !== over.id
    ) {
      <span class="hljs-comment">// Find the active container and over container</span>
      <span class="hljs-keyword">const</span> activeContainer = findValueOfItems(active.id, <span class="hljs-string">'item'</span>);
      <span class="hljs-keyword">const</span> overContainer = findValueOfItems(over.id, <span class="hljs-string">'item'</span>);

      <span class="hljs-comment">// If the active or over container is not found, return</span>
      <span class="hljs-keyword">if</span> (!activeContainer || !overContainer) <span class="hljs-keyword">return</span>;

      <span class="hljs-comment">// Find the index of the active and over container</span>
      <span class="hljs-keyword">const</span> activeContainerIndex = containers.findIndex(
        <span class="hljs-function">(<span class="hljs-params">container</span>) =&gt;</span> container.id === activeContainer.id,
      );
      <span class="hljs-keyword">const</span> overContainerIndex = containers.findIndex(
        <span class="hljs-function">(<span class="hljs-params">container</span>) =&gt;</span> container.id === overContainer.id,
      );

      <span class="hljs-comment">// Find the index of the active and over item</span>
      <span class="hljs-keyword">const</span> activeitemIndex = activeContainer.items.findIndex(
        <span class="hljs-function">(<span class="hljs-params">item</span>) =&gt;</span> item.id === active.id,
      );
      <span class="hljs-keyword">const</span> overitemIndex = overContainer.items.findIndex(
        <span class="hljs-function">(<span class="hljs-params">item</span>) =&gt;</span> item.id === over.id,
      );
      <span class="hljs-comment">// In the same container</span>
      <span class="hljs-keyword">if</span> (activeContainerIndex === overContainerIndex) {
        <span class="hljs-keyword">let</span> newItems = [...containers];
        newItems[activeContainerIndex].items = arrayMove(
          newItems[activeContainerIndex].items,
          activeitemIndex,
          overitemIndex,
        );

        setContainers(newItems);
      } <span class="hljs-keyword">else</span> {
        <span class="hljs-comment">// In different containers</span>
        <span class="hljs-keyword">let</span> newItems = [...containers];
        <span class="hljs-keyword">const</span> [removeditem] = newItems[activeContainerIndex].items.splice(
          activeitemIndex,
          <span class="hljs-number">1</span>,
        );
        newItems[overContainerIndex].items.splice(
          overitemIndex,
          <span class="hljs-number">0</span>,
          removeditem,
        );
        setContainers(newItems);
      }
    }

    <span class="hljs-comment">// Handling Item Drop Into a Container</span>
    <span class="hljs-keyword">if</span> (
      active.id.toString().includes(<span class="hljs-string">'item'</span>) &amp;&amp;
      over?.id.toString().includes(<span class="hljs-string">'container'</span>) &amp;&amp;
      active &amp;&amp;
      over &amp;&amp;
      active.id !== over.id
    ) {
      <span class="hljs-comment">// Find the active and over container</span>
      <span class="hljs-keyword">const</span> activeContainer = findValueOfItems(active.id, <span class="hljs-string">'item'</span>);
      <span class="hljs-keyword">const</span> overContainer = findValueOfItems(over.id, <span class="hljs-string">'container'</span>);

      <span class="hljs-comment">// If the active or over container is not found, return</span>
      <span class="hljs-keyword">if</span> (!activeContainer || !overContainer) <span class="hljs-keyword">return</span>;

      <span class="hljs-comment">// Find the index of the active and over container</span>
      <span class="hljs-keyword">const</span> activeContainerIndex = containers.findIndex(
        <span class="hljs-function">(<span class="hljs-params">container</span>) =&gt;</span> container.id === activeContainer.id,
      );
      <span class="hljs-keyword">const</span> overContainerIndex = containers.findIndex(
        <span class="hljs-function">(<span class="hljs-params">container</span>) =&gt;</span> container.id === overContainer.id,
      );

      <span class="hljs-comment">// Find the index of the active and over item</span>
      <span class="hljs-keyword">const</span> activeitemIndex = activeContainer.items.findIndex(
        <span class="hljs-function">(<span class="hljs-params">item</span>) =&gt;</span> item.id === active.id,
      );

      <span class="hljs-comment">// Remove the active item from the active container and add it to the over container</span>
      <span class="hljs-keyword">let</span> newItems = [...containers];
      <span class="hljs-keyword">const</span> [removeditem] = newItems[activeContainerIndex].items.splice(
        activeitemIndex,
        <span class="hljs-number">1</span>,
      );
      newItems[overContainerIndex].items.push(removeditem);
      setContainers(newItems);
    }
  };
</code></pre>
<h3 id="heading-handle-drag-end">Handle Drag End -</h3>
<p>this function is going to be similar to <code>handleDragMove</code> but in this function, we are also going to handle the scenarios in which we are sorting the <code>containers</code>.</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">handleDragEnd</span>(<span class="hljs-params">event: DragEndEvent</span>) </span>{
    <span class="hljs-keyword">const</span> { active, over } = event;

    <span class="hljs-comment">// Handling Container Sorting</span>
    <span class="hljs-keyword">if</span> (
      active.id.toString().includes(<span class="hljs-string">'container'</span>) &amp;&amp;
      over?.id.toString().includes(<span class="hljs-string">'container'</span>) &amp;&amp;
      active &amp;&amp;
      over &amp;&amp;
      active.id !== over.id
    ) {
      <span class="hljs-comment">// Find the index of the active and over container</span>
      <span class="hljs-keyword">const</span> activeContainerIndex = containers.findIndex(
        <span class="hljs-function">(<span class="hljs-params">container</span>) =&gt;</span> container.id === active.id,
      );
      <span class="hljs-keyword">const</span> overContainerIndex = containers.findIndex(
        <span class="hljs-function">(<span class="hljs-params">container</span>) =&gt;</span> container.id === over.id,
      );
      <span class="hljs-comment">// Swap the active and over container</span>
      <span class="hljs-keyword">let</span> newItems = [...containers];
      newItems = arrayMove(newItems, activeContainerIndex, overContainerIndex);
      setContainers(newItems);
    }

    <span class="hljs-comment">// Handling item Sorting</span>
    <span class="hljs-keyword">if</span> (
      active.id.toString().includes(<span class="hljs-string">'item'</span>) &amp;&amp;
      over?.id.toString().includes(<span class="hljs-string">'item'</span>) &amp;&amp;
      active &amp;&amp;
      over &amp;&amp;
      active.id !== over.id
    ) {
      <span class="hljs-comment">// Find the active and over container</span>
      <span class="hljs-keyword">const</span> activeContainer = findValueOfItems(active.id, <span class="hljs-string">'item'</span>);
      <span class="hljs-keyword">const</span> overContainer = findValueOfItems(over.id, <span class="hljs-string">'item'</span>);

      <span class="hljs-comment">// If the active or over container is not found, return</span>
      <span class="hljs-keyword">if</span> (!activeContainer || !overContainer) <span class="hljs-keyword">return</span>;
      <span class="hljs-comment">// Find the index of the active and over container</span>
      <span class="hljs-keyword">const</span> activeContainerIndex = containers.findIndex(
        <span class="hljs-function">(<span class="hljs-params">container</span>) =&gt;</span> container.id === activeContainer.id,
      );
      <span class="hljs-keyword">const</span> overContainerIndex = containers.findIndex(
        <span class="hljs-function">(<span class="hljs-params">container</span>) =&gt;</span> container.id === overContainer.id,
      );
      <span class="hljs-comment">// Find the index of the active and over item</span>
      <span class="hljs-keyword">const</span> activeitemIndex = activeContainer.items.findIndex(
        <span class="hljs-function">(<span class="hljs-params">item</span>) =&gt;</span> item.id === active.id,
      );
      <span class="hljs-keyword">const</span> overitemIndex = overContainer.items.findIndex(
        <span class="hljs-function">(<span class="hljs-params">item</span>) =&gt;</span> item.id === over.id,
      );

      <span class="hljs-comment">// In the same container</span>
      <span class="hljs-keyword">if</span> (activeContainerIndex === overContainerIndex) {
        <span class="hljs-keyword">let</span> newItems = [...containers];
        newItems[activeContainerIndex].items = arrayMove(
          newItems[activeContainerIndex].items,
          activeitemIndex,
          overitemIndex,
        );
        setContainers(newItems);
      } <span class="hljs-keyword">else</span> {
        <span class="hljs-comment">// In different containers</span>
        <span class="hljs-keyword">let</span> newItems = [...containers];
        <span class="hljs-keyword">const</span> [removeditem] = newItems[activeContainerIndex].items.splice(
          activeitemIndex,
          <span class="hljs-number">1</span>,
        );
        newItems[overContainerIndex].items.splice(
          overitemIndex,
          <span class="hljs-number">0</span>,
          removeditem,
        );
        setContainers(newItems);
      }
    }
    <span class="hljs-comment">// Handling item dropping into Container</span>
    <span class="hljs-keyword">if</span> (
      active.id.toString().includes(<span class="hljs-string">'item'</span>) &amp;&amp;
      over?.id.toString().includes(<span class="hljs-string">'container'</span>) &amp;&amp;
      active &amp;&amp;
      over &amp;&amp;
      active.id !== over.id
    ) {
      <span class="hljs-comment">// Find the active and over container</span>
      <span class="hljs-keyword">const</span> activeContainer = findValueOfItems(active.id, <span class="hljs-string">'item'</span>);
      <span class="hljs-keyword">const</span> overContainer = findValueOfItems(over.id, <span class="hljs-string">'container'</span>);

      <span class="hljs-comment">// If the active or over container is not found, return</span>
      <span class="hljs-keyword">if</span> (!activeContainer || !overContainer) <span class="hljs-keyword">return</span>;
      <span class="hljs-comment">// Find the index of the active and over container</span>
      <span class="hljs-keyword">const</span> activeContainerIndex = containers.findIndex(
        <span class="hljs-function">(<span class="hljs-params">container</span>) =&gt;</span> container.id === activeContainer.id,
      );
      <span class="hljs-keyword">const</span> overContainerIndex = containers.findIndex(
        <span class="hljs-function">(<span class="hljs-params">container</span>) =&gt;</span> container.id === overContainer.id,
      );
      <span class="hljs-comment">// Find the index of the active and over item</span>
      <span class="hljs-keyword">const</span> activeitemIndex = activeContainer.items.findIndex(
        <span class="hljs-function">(<span class="hljs-params">item</span>) =&gt;</span> item.id === active.id,
      );

      <span class="hljs-keyword">let</span> newItems = [...containers];
      <span class="hljs-keyword">const</span> [removeditem] = newItems[activeContainerIndex].items.splice(
        activeitemIndex,
        <span class="hljs-number">1</span>,
      );
      newItems[overContainerIndex].items.push(removeditem);
      setContainers(newItems);
    }
    setActiveId(<span class="hljs-literal">null</span>);
  }
</code></pre>
<p>Now let's add some dummy content to our <code>containers</code> state and see if we can sort <code>items</code> and <code>containers</code>.</p>
<pre><code class="lang-javascript">  <span class="hljs-keyword">const</span> [containers, setContainers] = useState&lt;DNDType[]&gt;([
    {
      <span class="hljs-attr">id</span>: <span class="hljs-string">`container-<span class="hljs-subst">${uuidv4()}</span>`</span>,
      <span class="hljs-attr">title</span>: <span class="hljs-string">'Container 1'</span>,
      <span class="hljs-attr">items</span>: [
        {
          <span class="hljs-attr">id</span>: <span class="hljs-string">`item-<span class="hljs-subst">${uuidv4()}</span>`</span>,
          <span class="hljs-attr">title</span>: <span class="hljs-string">'Item 1'</span>,
        },
      ],
    },
    {
      <span class="hljs-attr">id</span>: <span class="hljs-string">`container-<span class="hljs-subst">${uuidv4()}</span>`</span>,
      <span class="hljs-attr">title</span>: <span class="hljs-string">'Container 2'</span>,
      <span class="hljs-attr">items</span>: [
        {
          <span class="hljs-attr">id</span>: <span class="hljs-string">`item-<span class="hljs-subst">${uuidv4()}</span>`</span>,
          <span class="hljs-attr">title</span>: <span class="hljs-string">'Item 2'</span>,
        },
      ],
    },
  ]);
</code></pre>
<p>Now, we can sort the <code>items</code> and <code>containers</code>.</p>
<h3 id="heading-add-container-modal">Add Container Modal -</h3>
<p>Now that we have core functionality working for our Kanban board let's add the ability to add a <code>container</code>.</p>
<ul>
<li><p>First, we are going to add a button to add a container</p>
</li>
<li><p>When we click that button we are going to open a modal and let the user enter the name for the container and then append that container to our container's state.</p>
</li>
</ul>
<pre><code class="lang-javascript">  <span class="hljs-keyword">const</span> onAddContainer = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">if</span> (!containerName) <span class="hljs-keyword">return</span>;
    <span class="hljs-keyword">const</span> id = <span class="hljs-string">`container-<span class="hljs-subst">${uuidv4()}</span>`</span>;
    setContainers([
      ...containers,
      {
        id,
        <span class="hljs-attr">title</span>: containerName,
        <span class="hljs-attr">items</span>: [],
      },
    ]);
    setContainerName(<span class="hljs-string">''</span>);
    setShowAddContainerModal(<span class="hljs-literal">false</span>);
  };
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1691413695241/ef772403-9a5e-47e2-b1c1-06d27fced01e.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-add-item-modal">Add Item Modal</h3>
<p>After adding the functionality of creating a container, we can similarly add the functionality to create an item in a particular container using <code>currentContainerId</code> state.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> onAddItem = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">if</span> (!itemName) <span class="hljs-keyword">return</span>;
    <span class="hljs-keyword">const</span> id = <span class="hljs-string">`item-<span class="hljs-subst">${uuidv4()}</span>`</span>;
    <span class="hljs-keyword">const</span> container = containers.find(<span class="hljs-function">(<span class="hljs-params">item</span>) =&gt;</span> item.id === currentContainerId);
    <span class="hljs-keyword">if</span> (!container) <span class="hljs-keyword">return</span>;
    container.items.push({
      id,
      <span class="hljs-attr">title</span>: itemName,
    });
    setContainers([...containers]);
    setItemName(<span class="hljs-string">''</span>);
    setShowAddItemModal(<span class="hljs-literal">false</span>);
  };
</code></pre>
<h3 id="heading-drag-overlay">Drag Overlay</h3>
<p>At last, we need to add a drag overlay so that we can render a preview of the element we are dragging wither <code>container</code> or <code>items</code>.</p>
<pre><code class="lang-javascript"> &lt;DragOverlay adjustScale={<span class="hljs-literal">false</span>}&gt;
              {<span class="hljs-comment">/* Drag Overlay For item Item */</span>}
              {activeId &amp;&amp; activeId.toString().includes(<span class="hljs-string">'item'</span>) &amp;&amp; (
                <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Items</span> <span class="hljs-attr">id</span>=<span class="hljs-string">{activeId}</span> <span class="hljs-attr">title</span>=<span class="hljs-string">{findItemTitle(activeId)}</span> /&gt;</span></span>
              )}
              {<span class="hljs-comment">/* Drag Overlay For Container */</span>}
              {activeId &amp;&amp; activeId.toString().includes(<span class="hljs-string">'container'</span>) &amp;&amp; (
                <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Container</span> <span class="hljs-attr">id</span>=<span class="hljs-string">{activeId}</span> <span class="hljs-attr">title</span>=<span class="hljs-string">{findContainerTitle(activeId)}</span>&gt;</span>
                  {findContainerItems(activeId).map((i) =&gt; (
                    <span class="hljs-tag">&lt;<span class="hljs-name">Items</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{i.id}</span> <span class="hljs-attr">title</span>=<span class="hljs-string">{i.title}</span> <span class="hljs-attr">id</span>=<span class="hljs-string">{i.id}</span> /&gt;</span>
                  ))}
                <span class="hljs-tag">&lt;/<span class="hljs-name">Container</span>&gt;</span></span>
              )}
            &lt;/DragOverlay&gt;
</code></pre>
<h3 id="heading-final-code">Final Code -</h3>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> { v4 <span class="hljs-keyword">as</span> uuidv4 } <span class="hljs-keyword">from</span> <span class="hljs-string">'uuid'</span>;

<span class="hljs-comment">// DnD</span>
<span class="hljs-keyword">import</span> {
  DndContext,
  DragEndEvent,
  DragMoveEvent,
  DragOverlay,
  DragStartEvent,
  KeyboardSensor,
  PointerSensor,
  UniqueIdentifier,
  closestCorners,
  useSensor,
  useSensors,
} <span class="hljs-keyword">from</span> <span class="hljs-string">'@dnd-kit/core'</span>;
<span class="hljs-keyword">import</span> {
  SortableContext,
  arrayMove,
  sortableKeyboardCoordinates,
} <span class="hljs-keyword">from</span> <span class="hljs-string">'@dnd-kit/sortable'</span>;

<span class="hljs-keyword">import</span> { Inter } <span class="hljs-keyword">from</span> <span class="hljs-string">'next/font/google'</span>;

<span class="hljs-comment">// Components</span>
<span class="hljs-keyword">import</span> Container <span class="hljs-keyword">from</span> <span class="hljs-string">'@/components/Container'</span>;
<span class="hljs-keyword">import</span> Items <span class="hljs-keyword">from</span> <span class="hljs-string">'@/components/Item'</span>;
<span class="hljs-keyword">import</span> Modal <span class="hljs-keyword">from</span> <span class="hljs-string">'@/components/Modal'</span>;
<span class="hljs-keyword">import</span> Input <span class="hljs-keyword">from</span> <span class="hljs-string">'@/components/Input'</span>;
<span class="hljs-keyword">import</span> { Button } <span class="hljs-keyword">from</span> <span class="hljs-string">'@/components/Button'</span>;

<span class="hljs-keyword">const</span> inter = Inter({ <span class="hljs-attr">subsets</span>: [<span class="hljs-string">'latin'</span>] });

type DNDType = {
  <span class="hljs-attr">id</span>: UniqueIdentifier;
  title: string;
  items: {
    <span class="hljs-attr">id</span>: UniqueIdentifier;
    title: string;
  }[];
};

<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">Home</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [containers, setContainers] = useState&lt;DNDType[]&gt;([]);
  <span class="hljs-keyword">const</span> [activeId, setActiveId] = useState&lt;UniqueIdentifier | <span class="hljs-literal">null</span>&gt;(<span class="hljs-literal">null</span>);
  <span class="hljs-keyword">const</span> [currentContainerId, setCurrentContainerId] =
    useState&lt;UniqueIdentifier&gt;();
  <span class="hljs-keyword">const</span> [containerName, setContainerName] = useState(<span class="hljs-string">''</span>);
  <span class="hljs-keyword">const</span> [itemName, setItemName] = useState(<span class="hljs-string">''</span>);
  <span class="hljs-keyword">const</span> [showAddContainerModal, setShowAddContainerModal] = useState(<span class="hljs-literal">false</span>);
  <span class="hljs-keyword">const</span> [showAddItemModal, setShowAddItemModal] = useState(<span class="hljs-literal">false</span>);

  <span class="hljs-keyword">const</span> onAddContainer = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">if</span> (!containerName) <span class="hljs-keyword">return</span>;
    <span class="hljs-keyword">const</span> id = <span class="hljs-string">`container-<span class="hljs-subst">${uuidv4()}</span>`</span>;
    setContainers([
      ...containers,
      {
        id,
        <span class="hljs-attr">title</span>: containerName,
        <span class="hljs-attr">items</span>: [],
      },
    ]);
    setContainerName(<span class="hljs-string">''</span>);
    setShowAddContainerModal(<span class="hljs-literal">false</span>);
  };

  <span class="hljs-keyword">const</span> onAddItem = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">if</span> (!itemName) <span class="hljs-keyword">return</span>;
    <span class="hljs-keyword">const</span> id = <span class="hljs-string">`item-<span class="hljs-subst">${uuidv4()}</span>`</span>;
    <span class="hljs-keyword">const</span> container = containers.find(<span class="hljs-function">(<span class="hljs-params">item</span>) =&gt;</span> item.id === currentContainerId);
    <span class="hljs-keyword">if</span> (!container) <span class="hljs-keyword">return</span>;
    container.items.push({
      id,
      <span class="hljs-attr">title</span>: itemName,
    });
    setContainers([...containers]);
    setItemName(<span class="hljs-string">''</span>);
    setShowAddItemModal(<span class="hljs-literal">false</span>);
  };

  <span class="hljs-comment">// Find the value of the items</span>
  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">findValueOfItems</span>(<span class="hljs-params">id: UniqueIdentifier | undefined, type: string</span>) </span>{
    <span class="hljs-keyword">if</span> (type === <span class="hljs-string">'container'</span>) {
      <span class="hljs-keyword">return</span> containers.find(<span class="hljs-function">(<span class="hljs-params">item</span>) =&gt;</span> item.id === id);
    }
    <span class="hljs-keyword">if</span> (type === <span class="hljs-string">'item'</span>) {
      <span class="hljs-keyword">return</span> containers.find(<span class="hljs-function">(<span class="hljs-params">container</span>) =&gt;</span>
        container.items.find(<span class="hljs-function">(<span class="hljs-params">item</span>) =&gt;</span> item.id === id),
      );
    }
  }

  <span class="hljs-keyword">const</span> findItemTitle = <span class="hljs-function">(<span class="hljs-params">id: UniqueIdentifier | <span class="hljs-literal">undefined</span></span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> container = findValueOfItems(id, <span class="hljs-string">'item'</span>);
    <span class="hljs-keyword">if</span> (!container) <span class="hljs-keyword">return</span> <span class="hljs-string">''</span>;
    <span class="hljs-keyword">const</span> item = container.items.find(<span class="hljs-function">(<span class="hljs-params">item</span>) =&gt;</span> item.id === id);
    <span class="hljs-keyword">if</span> (!item) <span class="hljs-keyword">return</span> <span class="hljs-string">''</span>;
    <span class="hljs-keyword">return</span> item.title;
  };

  <span class="hljs-keyword">const</span> findContainerTitle = <span class="hljs-function">(<span class="hljs-params">id: UniqueIdentifier | <span class="hljs-literal">undefined</span></span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> container = findValueOfItems(id, <span class="hljs-string">'container'</span>);
    <span class="hljs-keyword">if</span> (!container) <span class="hljs-keyword">return</span> <span class="hljs-string">''</span>;
    <span class="hljs-keyword">return</span> container.title;
  };

  <span class="hljs-keyword">const</span> findContainerItems = <span class="hljs-function">(<span class="hljs-params">id: UniqueIdentifier | <span class="hljs-literal">undefined</span></span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> container = findValueOfItems(id, <span class="hljs-string">'container'</span>);
    <span class="hljs-keyword">if</span> (!container) <span class="hljs-keyword">return</span> [];
    <span class="hljs-keyword">return</span> container.items;
  };

  <span class="hljs-comment">// DND Handlers</span>
  <span class="hljs-keyword">const</span> sensors = useSensors(
    useSensor(PointerSensor),
    useSensor(KeyboardSensor, {
      <span class="hljs-attr">coordinateGetter</span>: sortableKeyboardCoordinates,
    }),
  );

  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">handleDragStart</span>(<span class="hljs-params">event: DragStartEvent</span>) </span>{
    <span class="hljs-keyword">const</span> { active } = event;
    <span class="hljs-keyword">const</span> { id } = active;
    setActiveId(id);
  }

  <span class="hljs-keyword">const</span> handleDragMove = <span class="hljs-function">(<span class="hljs-params">event: DragMoveEvent</span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> { active, over } = event;

    <span class="hljs-comment">// Handle Items Sorting</span>
    <span class="hljs-keyword">if</span> (
      active.id.toString().includes(<span class="hljs-string">'item'</span>) &amp;&amp;
      over?.id.toString().includes(<span class="hljs-string">'item'</span>) &amp;&amp;
      active &amp;&amp;
      over &amp;&amp;
      active.id !== over.id
    ) {
      <span class="hljs-comment">// Find the active container and over container</span>
      <span class="hljs-keyword">const</span> activeContainer = findValueOfItems(active.id, <span class="hljs-string">'item'</span>);
      <span class="hljs-keyword">const</span> overContainer = findValueOfItems(over.id, <span class="hljs-string">'item'</span>);

      <span class="hljs-comment">// If the active or over container is not found, return</span>
      <span class="hljs-keyword">if</span> (!activeContainer || !overContainer) <span class="hljs-keyword">return</span>;

      <span class="hljs-comment">// Find the index of the active and over container</span>
      <span class="hljs-keyword">const</span> activeContainerIndex = containers.findIndex(
        <span class="hljs-function">(<span class="hljs-params">container</span>) =&gt;</span> container.id === activeContainer.id,
      );
      <span class="hljs-keyword">const</span> overContainerIndex = containers.findIndex(
        <span class="hljs-function">(<span class="hljs-params">container</span>) =&gt;</span> container.id === overContainer.id,
      );

      <span class="hljs-comment">// Find the index of the active and over item</span>
      <span class="hljs-keyword">const</span> activeitemIndex = activeContainer.items.findIndex(
        <span class="hljs-function">(<span class="hljs-params">item</span>) =&gt;</span> item.id === active.id,
      );
      <span class="hljs-keyword">const</span> overitemIndex = overContainer.items.findIndex(
        <span class="hljs-function">(<span class="hljs-params">item</span>) =&gt;</span> item.id === over.id,
      );
      <span class="hljs-comment">// In the same container</span>
      <span class="hljs-keyword">if</span> (activeContainerIndex === overContainerIndex) {
        <span class="hljs-keyword">let</span> newItems = [...containers];
        newItems[activeContainerIndex].items = arrayMove(
          newItems[activeContainerIndex].items,
          activeitemIndex,
          overitemIndex,
        );

        setContainers(newItems);
      } <span class="hljs-keyword">else</span> {
        <span class="hljs-comment">// In different containers</span>
        <span class="hljs-keyword">let</span> newItems = [...containers];
        <span class="hljs-keyword">const</span> [removeditem] = newItems[activeContainerIndex].items.splice(
          activeitemIndex,
          <span class="hljs-number">1</span>,
        );
        newItems[overContainerIndex].items.splice(
          overitemIndex,
          <span class="hljs-number">0</span>,
          removeditem,
        );
        setContainers(newItems);
      }
    }

    <span class="hljs-comment">// Handling Item Drop Into a Container</span>
    <span class="hljs-keyword">if</span> (
      active.id.toString().includes(<span class="hljs-string">'item'</span>) &amp;&amp;
      over?.id.toString().includes(<span class="hljs-string">'container'</span>) &amp;&amp;
      active &amp;&amp;
      over &amp;&amp;
      active.id !== over.id
    ) {
      <span class="hljs-comment">// Find the active and over container</span>
      <span class="hljs-keyword">const</span> activeContainer = findValueOfItems(active.id, <span class="hljs-string">'item'</span>);
      <span class="hljs-keyword">const</span> overContainer = findValueOfItems(over.id, <span class="hljs-string">'container'</span>);

      <span class="hljs-comment">// If the active or over container is not found, return</span>
      <span class="hljs-keyword">if</span> (!activeContainer || !overContainer) <span class="hljs-keyword">return</span>;

      <span class="hljs-comment">// Find the index of the active and over container</span>
      <span class="hljs-keyword">const</span> activeContainerIndex = containers.findIndex(
        <span class="hljs-function">(<span class="hljs-params">container</span>) =&gt;</span> container.id === activeContainer.id,
      );
      <span class="hljs-keyword">const</span> overContainerIndex = containers.findIndex(
        <span class="hljs-function">(<span class="hljs-params">container</span>) =&gt;</span> container.id === overContainer.id,
      );

      <span class="hljs-comment">// Find the index of the active and over item</span>
      <span class="hljs-keyword">const</span> activeitemIndex = activeContainer.items.findIndex(
        <span class="hljs-function">(<span class="hljs-params">item</span>) =&gt;</span> item.id === active.id,
      );

      <span class="hljs-comment">// Remove the active item from the active container and add it to the over container</span>
      <span class="hljs-keyword">let</span> newItems = [...containers];
      <span class="hljs-keyword">const</span> [removeditem] = newItems[activeContainerIndex].items.splice(
        activeitemIndex,
        <span class="hljs-number">1</span>,
      );
      newItems[overContainerIndex].items.push(removeditem);
      setContainers(newItems);
    }
  };

  <span class="hljs-comment">// This is the function that handles the sorting of the containers and items when the user is done dragging.</span>
  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">handleDragEnd</span>(<span class="hljs-params">event: DragEndEvent</span>) </span>{
    <span class="hljs-keyword">const</span> { active, over } = event;

    <span class="hljs-comment">// Handling Container Sorting</span>
    <span class="hljs-keyword">if</span> (
      active.id.toString().includes(<span class="hljs-string">'container'</span>) &amp;&amp;
      over?.id.toString().includes(<span class="hljs-string">'container'</span>) &amp;&amp;
      active &amp;&amp;
      over &amp;&amp;
      active.id !== over.id
    ) {
      <span class="hljs-comment">// Find the index of the active and over container</span>
      <span class="hljs-keyword">const</span> activeContainerIndex = containers.findIndex(
        <span class="hljs-function">(<span class="hljs-params">container</span>) =&gt;</span> container.id === active.id,
      );
      <span class="hljs-keyword">const</span> overContainerIndex = containers.findIndex(
        <span class="hljs-function">(<span class="hljs-params">container</span>) =&gt;</span> container.id === over.id,
      );
      <span class="hljs-comment">// Swap the active and over container</span>
      <span class="hljs-keyword">let</span> newItems = [...containers];
      newItems = arrayMove(newItems, activeContainerIndex, overContainerIndex);
      setContainers(newItems);
    }

    <span class="hljs-comment">// Handling item Sorting</span>
    <span class="hljs-keyword">if</span> (
      active.id.toString().includes(<span class="hljs-string">'item'</span>) &amp;&amp;
      over?.id.toString().includes(<span class="hljs-string">'item'</span>) &amp;&amp;
      active &amp;&amp;
      over &amp;&amp;
      active.id !== over.id
    ) {
      <span class="hljs-comment">// Find the active and over container</span>
      <span class="hljs-keyword">const</span> activeContainer = findValueOfItems(active.id, <span class="hljs-string">'item'</span>);
      <span class="hljs-keyword">const</span> overContainer = findValueOfItems(over.id, <span class="hljs-string">'item'</span>);

      <span class="hljs-comment">// If the active or over container is not found, return</span>
      <span class="hljs-keyword">if</span> (!activeContainer || !overContainer) <span class="hljs-keyword">return</span>;
      <span class="hljs-comment">// Find the index of the active and over container</span>
      <span class="hljs-keyword">const</span> activeContainerIndex = containers.findIndex(
        <span class="hljs-function">(<span class="hljs-params">container</span>) =&gt;</span> container.id === activeContainer.id,
      );
      <span class="hljs-keyword">const</span> overContainerIndex = containers.findIndex(
        <span class="hljs-function">(<span class="hljs-params">container</span>) =&gt;</span> container.id === overContainer.id,
      );
      <span class="hljs-comment">// Find the index of the active and over item</span>
      <span class="hljs-keyword">const</span> activeitemIndex = activeContainer.items.findIndex(
        <span class="hljs-function">(<span class="hljs-params">item</span>) =&gt;</span> item.id === active.id,
      );
      <span class="hljs-keyword">const</span> overitemIndex = overContainer.items.findIndex(
        <span class="hljs-function">(<span class="hljs-params">item</span>) =&gt;</span> item.id === over.id,
      );

      <span class="hljs-comment">// In the same container</span>
      <span class="hljs-keyword">if</span> (activeContainerIndex === overContainerIndex) {
        <span class="hljs-keyword">let</span> newItems = [...containers];
        newItems[activeContainerIndex].items = arrayMove(
          newItems[activeContainerIndex].items,
          activeitemIndex,
          overitemIndex,
        );
        setContainers(newItems);
      } <span class="hljs-keyword">else</span> {
        <span class="hljs-comment">// In different containers</span>
        <span class="hljs-keyword">let</span> newItems = [...containers];
        <span class="hljs-keyword">const</span> [removeditem] = newItems[activeContainerIndex].items.splice(
          activeitemIndex,
          <span class="hljs-number">1</span>,
        );
        newItems[overContainerIndex].items.splice(
          overitemIndex,
          <span class="hljs-number">0</span>,
          removeditem,
        );
        setContainers(newItems);
      }
    }
    <span class="hljs-comment">// Handling item dropping into Container</span>
    <span class="hljs-keyword">if</span> (
      active.id.toString().includes(<span class="hljs-string">'item'</span>) &amp;&amp;
      over?.id.toString().includes(<span class="hljs-string">'container'</span>) &amp;&amp;
      active &amp;&amp;
      over &amp;&amp;
      active.id !== over.id
    ) {
      <span class="hljs-comment">// Find the active and over container</span>
      <span class="hljs-keyword">const</span> activeContainer = findValueOfItems(active.id, <span class="hljs-string">'item'</span>);
      <span class="hljs-keyword">const</span> overContainer = findValueOfItems(over.id, <span class="hljs-string">'container'</span>);

      <span class="hljs-comment">// If the active or over container is not found, return</span>
      <span class="hljs-keyword">if</span> (!activeContainer || !overContainer) <span class="hljs-keyword">return</span>;
      <span class="hljs-comment">// Find the index of the active and over container</span>
      <span class="hljs-keyword">const</span> activeContainerIndex = containers.findIndex(
        <span class="hljs-function">(<span class="hljs-params">container</span>) =&gt;</span> container.id === activeContainer.id,
      );
      <span class="hljs-keyword">const</span> overContainerIndex = containers.findIndex(
        <span class="hljs-function">(<span class="hljs-params">container</span>) =&gt;</span> container.id === overContainer.id,
      );
      <span class="hljs-comment">// Find the index of the active and over item</span>
      <span class="hljs-keyword">const</span> activeitemIndex = activeContainer.items.findIndex(
        <span class="hljs-function">(<span class="hljs-params">item</span>) =&gt;</span> item.id === active.id,
      );

      <span class="hljs-keyword">let</span> newItems = [...containers];
      <span class="hljs-keyword">const</span> [removeditem] = newItems[activeContainerIndex].items.splice(
        activeitemIndex,
        <span class="hljs-number">1</span>,
      );
      newItems[overContainerIndex].items.push(removeditem);
      setContainers(newItems);
    }
    setActiveId(<span class="hljs-literal">null</span>);
  }

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"mx-auto max-w-7xl py-10"</span>&gt;</span>
      {/* Add Container Modal */}
      <span class="hljs-tag">&lt;<span class="hljs-name">Modal</span>
        <span class="hljs-attr">showModal</span>=<span class="hljs-string">{showAddContainerModal}</span>
        <span class="hljs-attr">setShowModal</span>=<span class="hljs-string">{setShowAddContainerModal}</span>
      &gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex flex-col w-full items-start gap-y-4"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-gray-800 text-3xl font-bold"</span>&gt;</span>Add Container<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Input</span>
            <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span>
            <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Container Title"</span>
            <span class="hljs-attr">name</span>=<span class="hljs-string">"containername"</span>
            <span class="hljs-attr">value</span>=<span class="hljs-string">{containerName}</span>
            <span class="hljs-attr">onChange</span>=<span class="hljs-string">{(e)</span> =&gt;</span> setContainerName(e.target.value)}
          /&gt;
          <span class="hljs-tag">&lt;<span class="hljs-name">Button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{onAddContainer}</span>&gt;</span>Add container<span class="hljs-tag">&lt;/<span class="hljs-name">Button</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">Modal</span>&gt;</span>
      {/* Add Item Modal */}
      <span class="hljs-tag">&lt;<span class="hljs-name">Modal</span> <span class="hljs-attr">showModal</span>=<span class="hljs-string">{showAddItemModal}</span> <span class="hljs-attr">setShowModal</span>=<span class="hljs-string">{setShowAddItemModal}</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex flex-col w-full items-start gap-y-4"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-gray-800 text-3xl font-bold"</span>&gt;</span>Add Item<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Input</span>
            <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span>
            <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Item Title"</span>
            <span class="hljs-attr">name</span>=<span class="hljs-string">"itemname"</span>
            <span class="hljs-attr">value</span>=<span class="hljs-string">{itemName}</span>
            <span class="hljs-attr">onChange</span>=<span class="hljs-string">{(e)</span> =&gt;</span> setItemName(e.target.value)}
          /&gt;
          <span class="hljs-tag">&lt;<span class="hljs-name">Button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{onAddItem}</span>&gt;</span>Add Item<span class="hljs-tag">&lt;/<span class="hljs-name">Button</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">Modal</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex items-center justify-between gap-y-2"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-gray-800 text-3xl font-bold"</span>&gt;</span>Dnd-kit Guide<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> setShowAddContainerModal(true)}&gt;
          Add Container
        <span class="hljs-tag">&lt;/<span class="hljs-name">Button</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"mt-10"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"grid grid-cols-3 gap-6"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">DndContext</span>
            <span class="hljs-attr">sensors</span>=<span class="hljs-string">{sensors}</span>
            <span class="hljs-attr">collisionDetection</span>=<span class="hljs-string">{closestCorners}</span>
            <span class="hljs-attr">onDragStart</span>=<span class="hljs-string">{handleDragStart}</span>
            <span class="hljs-attr">onDragMove</span>=<span class="hljs-string">{handleDragMove}</span>
            <span class="hljs-attr">onDragEnd</span>=<span class="hljs-string">{handleDragEnd}</span>
          &gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">SortableContext</span> <span class="hljs-attr">items</span>=<span class="hljs-string">{containers.map((i)</span> =&gt;</span> i.id)}&gt;
              {containers.map((container) =&gt; (
                <span class="hljs-tag">&lt;<span class="hljs-name">Container</span>
                  <span class="hljs-attr">id</span>=<span class="hljs-string">{container.id}</span>
                  <span class="hljs-attr">title</span>=<span class="hljs-string">{container.title}</span>
                  <span class="hljs-attr">key</span>=<span class="hljs-string">{container.id}</span>
                  <span class="hljs-attr">onAddItem</span>=<span class="hljs-string">{()</span> =&gt;</span> {
                    setShowAddItemModal(true);
                    setCurrentContainerId(container.id);
                  }}
                &gt;
                  <span class="hljs-tag">&lt;<span class="hljs-name">SortableContext</span> <span class="hljs-attr">items</span>=<span class="hljs-string">{container.items.map((i)</span> =&gt;</span> i.id)}&gt;
                    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex items-start flex-col gap-y-4"</span>&gt;</span>
                      {container.items.map((i) =&gt; (
                        <span class="hljs-tag">&lt;<span class="hljs-name">Items</span> <span class="hljs-attr">title</span>=<span class="hljs-string">{i.title}</span> <span class="hljs-attr">id</span>=<span class="hljs-string">{i.id}</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{i.id}</span> /&gt;</span>
                      ))}
                    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
                  <span class="hljs-tag">&lt;/<span class="hljs-name">SortableContext</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">Container</span>&gt;</span>
              ))}
            <span class="hljs-tag">&lt;/<span class="hljs-name">SortableContext</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">DragOverlay</span> <span class="hljs-attr">adjustScale</span>=<span class="hljs-string">{false}</span>&gt;</span>
              {/* Drag Overlay For item Item */}
              {activeId &amp;&amp; activeId.toString().includes('item') &amp;&amp; (
                <span class="hljs-tag">&lt;<span class="hljs-name">Items</span> <span class="hljs-attr">id</span>=<span class="hljs-string">{activeId}</span> <span class="hljs-attr">title</span>=<span class="hljs-string">{findItemTitle(activeId)}</span> /&gt;</span>
              )}
              {/* Drag Overlay For Container */}
              {activeId &amp;&amp; activeId.toString().includes('container') &amp;&amp; (
                <span class="hljs-tag">&lt;<span class="hljs-name">Container</span> <span class="hljs-attr">id</span>=<span class="hljs-string">{activeId}</span> <span class="hljs-attr">title</span>=<span class="hljs-string">{findContainerTitle(activeId)}</span>&gt;</span>
                  {findContainerItems(activeId).map((i) =&gt; (
                    <span class="hljs-tag">&lt;<span class="hljs-name">Items</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{i.id}</span> <span class="hljs-attr">title</span>=<span class="hljs-string">{i.title}</span> <span class="hljs-attr">id</span>=<span class="hljs-string">{i.id}</span> /&gt;</span>
                  ))}
                <span class="hljs-tag">&lt;/<span class="hljs-name">Container</span>&gt;</span>
              )}
            <span class="hljs-tag">&lt;/<span class="hljs-name">DragOverlay</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">DndContext</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p><strong>Github</strong> - <a target="_blank" href="https://github.com/chetanverma16/dndkit-guide">https://github.com/chetanverma16/dndkit-guide</a></p>
<h2 id="heading-conclusion"><strong>Conclusion</strong></h2>
<p>That's all I have for you! Hopefully, you learned something new.</p>
<p>If you enjoyed this article, give it a ❤️ so others can find it too.</p>
<p>For more such content, stay in touch on Twitter</p>
<p>Contact Me:</p>
<p><a target="_blank" href="http://chetanverma.com/"><strong>Portfolio</strong></a> | <a target="_blank" href="https://github.com/chetanverma16"><strong>Github</strong></a> | <a target="_blank" href="https://www.linkedin.com/in/chetanverma7/"><strong>LinkedIn</strong></a> | <a target="_blank" href="https://twitter.com/chetanvermaaa"><strong>Twitter</strong></a></p>
]]></content:encoded></item><item><title><![CDATA[How to create an awesome navigation menu using chakra-UI and framer-motion.]]></title><description><![CDATA[Introduction

Hey everyone in this tutorial we will create an awesome animated dropdown menu using chakra-UI and framer-motion.
we will be using next.js in this tutorial but you are free to use it on any react project.
so to get started let's set up ...]]></description><link>https://blog.chetanverma.com/how-to-create-an-awesome-navigation-menu-using-chakra-ui-and-framer-motion</link><guid isPermaLink="true">https://blog.chetanverma.com/how-to-create-an-awesome-navigation-menu-using-chakra-ui-and-framer-motion</guid><category><![CDATA[React]]></category><category><![CDATA[framer-motion]]></category><category><![CDATA[Chakra-ui]]></category><category><![CDATA[Next.js]]></category><category><![CDATA[animation]]></category><dc:creator><![CDATA[Chetan verma]]></dc:creator><pubDate>Wed, 25 Jan 2023 08:31:49 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1674635384929/851f25a7-6a7c-4ebd-83b0-28b35958332e.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-introduction">Introduction</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1674631565991/4564c102-6d0b-49aa-b3a4-1f706964a40c.gif" alt class="image--center mx-auto" /></p>
<p>Hey everyone in this tutorial we will create an awesome animated dropdown menu using chakra-UI and framer-motion.</p>
<p>we will be using next.js in this tutorial but you are free to use it on any react project.</p>
<p>so to get started let's set up our initial repository.</p>
<p>in your terminal run these commands</p>
<pre><code class="lang-bash">npx create-next-app my-project
<span class="hljs-built_in">cd</span> my-project
</code></pre>
<p>so once we are done with the next.js app setup.</p>
<p>let's go to <code>pages/_app.js</code> and wrap the whole app with <code>ChakraProvider</code> .</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> <span class="hljs-string">'@/styles/globals.css'</span>;
<span class="hljs-keyword">import</span> { ChakraProvider } <span class="hljs-keyword">from</span> <span class="hljs-string">'@chakra-ui/react'</span>;

<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">{ Component, pageProps }</span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ChakraProvider</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Component</span> {<span class="hljs-attr">...pageProps</span>} /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">ChakraProvider</span>&gt;</span></span>
  );
}
</code></pre>
<p>Now,<br />Let's create a new folder in the root of our repository and let's call it <code>components</code>.</p>
<p>under <code>components</code> let's create three subfolders - <code>Menu</code>, <code>MotionBox</code>, and <code>MotionText</code><br />so let's start with <code>Menu</code> the component that is gonna be the parent component of our awesome menu.</p>
<h3 id="heading-menu">Menu -</h3>
<p><code>Menu/index.js</code></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React, { createContext, useContext, useState } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> { Box, Flex } <span class="hljs-keyword">from</span> <span class="hljs-string">'@chakra-ui/react'</span>;
<span class="hljs-keyword">import</span> MotionBox <span class="hljs-keyword">from</span> <span class="hljs-string">'../MotionBox'</span>;
<span class="hljs-keyword">import</span> MotionText <span class="hljs-keyword">from</span> <span class="hljs-string">'../MotionText'</span>;

<span class="hljs-comment">// Framer Motion transition Property</span>
<span class="hljs-keyword">const</span> transition = {
  <span class="hljs-attr">type</span>: <span class="hljs-string">'spring'</span>,
  <span class="hljs-attr">mass</span>: <span class="hljs-number">0.5</span>,
  <span class="hljs-attr">damping</span>: <span class="hljs-number">11.5</span>,
  <span class="hljs-attr">stiffness</span>: <span class="hljs-number">100</span>,
  <span class="hljs-attr">restDelta</span>: <span class="hljs-number">0.001</span>,
  <span class="hljs-attr">restSpeed</span>: <span class="hljs-number">0.001</span>,
};

<span class="hljs-keyword">const</span> MenuContext = createContext(<span class="hljs-literal">null</span>);

<span class="hljs-keyword">const</span> useMenu = <span class="hljs-function">() =&gt;</span> useContext(MenuContext);

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> Menu = <span class="hljs-function">(<span class="hljs-params">{ children }</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> [activeItem, setActiveItem] = useState(<span class="hljs-literal">null</span>);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">MenuContext.Provider</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">activeItem</span>, <span class="hljs-attr">setActiveItem</span> }}&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Flex</span>
        <span class="hljs-attr">as</span>=<span class="hljs-string">"nav"</span>
        <span class="hljs-attr">display</span>=<span class="hljs-string">"inline-flex"</span>
        <span class="hljs-attr">p</span>=<span class="hljs-string">{8}</span>
        <span class="hljs-attr">gap</span>=<span class="hljs-string">{8}</span>
        <span class="hljs-attr">onMouseLeave</span>=<span class="hljs-string">{()</span> =&gt;</span> setActiveItem(null)}
      &gt;
        {children}
      <span class="hljs-tag">&lt;/<span class="hljs-name">Flex</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">MenuContext.Provider</span>&gt;</span></span>
  );
};
</code></pre>
<p>about <code>Menu</code> Component -</p>
<ul>
<li><p>It has a state which is <code>activeItem</code>, which will help us in determining and setting the currently active item which is hovered over.</p>
</li>
<li><p>we are using <code>useContext</code> hook to create a MenuContext which will help us in passing our state to other components.</p>
</li>
<li><p>we are wrapping the <code>children</code> of our component with <code>Flex</code> provided by chakra so that we can align the items in line.</p>
</li>
</ul>
<p>now let's create another component in <code>Menu/index.js</code> which is gonna be <code>MenuItem</code></p>
<h3 id="heading-menu-item">Menu Item -</h3>
<p><code>MenuItem</code></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React, { createContext, useContext, useState } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> { Box, Flex } <span class="hljs-keyword">from</span> <span class="hljs-string">'@chakra-ui/react'</span>;
<span class="hljs-keyword">import</span> MotionBox <span class="hljs-keyword">from</span> <span class="hljs-string">'../MotionBox'</span>;
<span class="hljs-keyword">import</span> MotionText <span class="hljs-keyword">from</span> <span class="hljs-string">'../MotionText'</span>;

<span class="hljs-keyword">const</span> transition = {
  <span class="hljs-attr">type</span>: <span class="hljs-string">'spring'</span>,
  <span class="hljs-attr">mass</span>: <span class="hljs-number">0.5</span>,
  <span class="hljs-attr">damping</span>: <span class="hljs-number">11.5</span>,
  <span class="hljs-attr">stiffness</span>: <span class="hljs-number">100</span>,
  <span class="hljs-attr">restDelta</span>: <span class="hljs-number">0.001</span>,
  <span class="hljs-attr">restSpeed</span>: <span class="hljs-number">0.001</span>,
};

<span class="hljs-keyword">const</span> MenuContext = createContext(<span class="hljs-literal">null</span>);

<span class="hljs-keyword">const</span> useMenu = <span class="hljs-function">() =&gt;</span> useContext(MenuContext);

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> MenuItem = <span class="hljs-function">(<span class="hljs-params">{ item, children }</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> menu = useMenu();
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Box</span>
      <span class="hljs-attr">pos</span>=<span class="hljs-string">"relative"</span>
      <span class="hljs-attr">color</span>=<span class="hljs-string">"white"</span>
      <span class="hljs-attr">onMouseEnter</span>=<span class="hljs-string">{()</span> =&gt;</span> {
        menu.setActiveItem(item);
      }}
    &gt;
      <span class="hljs-tag">&lt;<span class="hljs-name">MotionText</span>
        <span class="hljs-attr">color</span>=<span class="hljs-string">"rgba(0,0,0, 0.5)"</span>
        <span class="hljs-attr">animate</span>=<span class="hljs-string">{{</span>
          <span class="hljs-attr">color:</span>
            <span class="hljs-attr">menu.activeItem</span> === <span class="hljs-string">item</span> ? '<span class="hljs-attr">rgba</span>(<span class="hljs-attr">0</span>,<span class="hljs-attr">0</span>,<span class="hljs-attr">0</span>, <span class="hljs-attr">1</span>)' <span class="hljs-attr">:</span> '<span class="hljs-attr">rgba</span>(<span class="hljs-attr">0</span>,<span class="hljs-attr">0</span>,<span class="hljs-attr">0</span>, <span class="hljs-attr">0.5</span>)',
        }}
        <span class="hljs-attr">transition</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">duration:</span> <span class="hljs-attr">0.25</span> }}
        <span class="hljs-attr">cursor</span>=<span class="hljs-string">"pointer"</span>
      &gt;</span>
        {item}
      <span class="hljs-tag">&lt;/<span class="hljs-name">MotionText</span>&gt;</span>
      {menu.activeItem !== null &amp;&amp; (
        <span class="hljs-tag">&lt;<span class="hljs-name">MotionBox</span>
          <span class="hljs-attr">initial</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">opacity:</span> <span class="hljs-attr">0</span>, <span class="hljs-attr">scale:</span> <span class="hljs-attr">0.85</span> }}
          <span class="hljs-attr">animate</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">opacity:</span> <span class="hljs-attr">1</span>, <span class="hljs-attr">scale:</span> <span class="hljs-attr">1</span> }}
          <span class="hljs-attr">transition</span>=<span class="hljs-string">{transition}</span>
        &gt;</span>
          {menu.activeItem === item &amp;&amp; (
            <span class="hljs-tag">&lt;<span class="hljs-name">Box</span>
              <span class="hljs-attr">pos</span>=<span class="hljs-string">"absolute"</span>
              <span class="hljs-attr">top</span>=<span class="hljs-string">"calc(100% + 1rem)"</span>
              <span class="hljs-attr">left</span>=<span class="hljs-string">"50%"</span>
              <span class="hljs-attr">transform</span>=<span class="hljs-string">"translateX(-50%)"</span>
            &gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">MotionBox</span>
                <span class="hljs-attr">layoutId</span>=<span class="hljs-string">"active"</span>
                <span class="hljs-attr">bg</span>=<span class="hljs-string">"gray.200"</span>
                <span class="hljs-attr">rounded</span>=<span class="hljs-string">"2xl"</span>
                <span class="hljs-attr">overflow</span>=<span class="hljs-string">"hidden"</span>
                <span class="hljs-attr">borderWidth</span>=<span class="hljs-string">"1px"</span>
                <span class="hljs-attr">borderColor</span>=<span class="hljs-string">"whiteAlpha.200"</span>
                <span class="hljs-attr">transition</span>=<span class="hljs-string">{transition}</span>
              &gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">MotionBox</span> <span class="hljs-attr">layout</span> <span class="hljs-attr">w</span>=<span class="hljs-string">"max-content"</span> <span class="hljs-attr">h</span>=<span class="hljs-string">"100%"</span> <span class="hljs-attr">p</span>=<span class="hljs-string">{4}</span>&gt;</span>
                  {children}
                <span class="hljs-tag">&lt;/<span class="hljs-name">MotionBox</span>&gt;</span>
              <span class="hljs-tag">&lt;/<span class="hljs-name">MotionBox</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">Box</span>&gt;</span>
          )}
        <span class="hljs-tag">&lt;/<span class="hljs-name">MotionBox</span>&gt;</span>
      )}
    <span class="hljs-tag">&lt;/<span class="hljs-name">Box</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> Menu = <span class="hljs-function">(<span class="hljs-params">{ children }</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> [activeItem, setActiveItem] = useState(<span class="hljs-literal">null</span>);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">MenuContext.Provider</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">activeItem</span>, <span class="hljs-attr">setActiveItem</span> }}&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Flex</span>
        <span class="hljs-attr">as</span>=<span class="hljs-string">"nav"</span>
        <span class="hljs-attr">display</span>=<span class="hljs-string">"inline-flex"</span>
        <span class="hljs-attr">p</span>=<span class="hljs-string">{8}</span>
        <span class="hljs-attr">gap</span>=<span class="hljs-string">{8}</span>
        <span class="hljs-attr">onMouseLeave</span>=<span class="hljs-string">{()</span> =&gt;</span> setActiveItem(null)}
      &gt;
        {children}
      <span class="hljs-tag">&lt;/<span class="hljs-name">Flex</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">MenuContext.Provider</span>&gt;</span></span>
  );
};
</code></pre>
<p>about <code>MenuItem</code> -</p>
<ul>
<li><p>as the name suggests <code>MenuItem</code> will be used as an individual item on our menu.</p>
</li>
<li><p>it takes in two props <code>item</code>, <code>children</code>.</p>
</li>
<li><p><code>item</code> prop is used to set up the currently active item based on which we will show our <code>children</code> and also as the title for our dropdown menu.</p>
</li>
</ul>
<p>now that we have our basic structure added let's add some animation using <code>framer-motion</code></p>
<h3 id="heading-motion-box">Motion Box -</h3>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { motion, isValidMotionProp } <span class="hljs-keyword">from</span> <span class="hljs-string">'framer-motion'</span>;
<span class="hljs-keyword">import</span> { forwardRef, chakra } <span class="hljs-keyword">from</span> <span class="hljs-string">'@chakra-ui/react'</span>;

<span class="hljs-keyword">const</span> MotionBox = motion(
  forwardRef(<span class="hljs-function">(<span class="hljs-params">props, ref</span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> chakraProps = <span class="hljs-built_in">Object</span>.fromEntries(
      <span class="hljs-built_in">Object</span>.entries(props).filter(<span class="hljs-function">(<span class="hljs-params">[key]</span>) =&gt;</span> !isValidMotionProp(key)),
    );
    <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">chakra.div</span> <span class="hljs-attr">ref</span>=<span class="hljs-string">{ref}</span> {<span class="hljs-attr">...chakraProps</span>} /&gt;</span></span>;
  }),
);

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> MotionBox;
</code></pre>
<ul>
<li><p>MotionBox is used to animate the div or children, it is using <code>forwardRef</code> from React to forward the ref to our <code>chakra.div</code> and we are also wrapping the whole component under <code>motion</code> so that we can provide <code>framer-motion</code> properties to it.</p>
</li>
<li><p>we are also checking if the properties are valid or not using the utility function <code>isValidMotionProp</code> provided by <code>framer-motion</code>.</p>
</li>
</ul>
<p>Now that we have our animation wrapper for our div let's create the animation wrapper for our text.</p>
<h3 id="heading-motiontext">MotionText</h3>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { motion } <span class="hljs-keyword">from</span> <span class="hljs-string">'framer-motion'</span>;
<span class="hljs-keyword">import</span> { Text } <span class="hljs-keyword">from</span> <span class="hljs-string">'@chakra-ui/react'</span>;

<span class="hljs-keyword">const</span> MotionText = motion(Text);

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> MotionText;
</code></pre>
<p>ok so now that we have all of our components ready to go let's create our awesome navigation menu.</p>
<p>go to <code>pages/index.js</code> and create your menu using the components.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> { Stack, Text, Center, Link, HStack, Img } <span class="hljs-keyword">from</span> <span class="hljs-string">'@chakra-ui/react'</span>;
<span class="hljs-keyword">import</span> { Menu, MenuItem } <span class="hljs-keyword">from</span> <span class="hljs-string">'@/components/Menu'</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> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Center</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Menu</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">MenuItem</span> <span class="hljs-attr">item</span>=<span class="hljs-string">"Title One"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">HStack</span> <span class="hljs-attr">spacing</span>=<span class="hljs-string">{5}</span> <span class="hljs-attr">alignItems</span>=<span class="hljs-string">"start"</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">Stack</span> <span class="hljs-attr">spacing</span>=<span class="hljs-string">{1}</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">Text</span> <span class="hljs-attr">color</span>=<span class="hljs-string">"gray.800"</span> <span class="hljs-attr">fontWeight</span>=<span class="hljs-string">{600}</span>&gt;</span>
                  Heading
                <span class="hljs-tag">&lt;/<span class="hljs-name">Text</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">Link</span> <span class="hljs-attr">color</span>=<span class="hljs-string">"gray.600"</span>&gt;</span>Link One<span class="hljs-tag">&lt;/<span class="hljs-name">Link</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">Link</span> <span class="hljs-attr">color</span>=<span class="hljs-string">"gray.600"</span>&gt;</span>Link Two<span class="hljs-tag">&lt;/<span class="hljs-name">Link</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">Link</span> <span class="hljs-attr">color</span>=<span class="hljs-string">"gray.600"</span>&gt;</span>Link Three<span class="hljs-tag">&lt;/<span class="hljs-name">Link</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">Link</span> <span class="hljs-attr">color</span>=<span class="hljs-string">"gray.600"</span>&gt;</span>Link Four<span class="hljs-tag">&lt;/<span class="hljs-name">Link</span>&gt;</span>
              <span class="hljs-tag">&lt;/<span class="hljs-name">Stack</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">Stack</span> <span class="hljs-attr">spacing</span>=<span class="hljs-string">{2}</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">Text</span> <span class="hljs-attr">color</span>=<span class="hljs-string">"gray.800"</span> <span class="hljs-attr">fontWeight</span>=<span class="hljs-string">{600}</span>&gt;</span>
                  Showcase
                <span class="hljs-tag">&lt;/<span class="hljs-name">Text</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">Img</span>
                  <span class="hljs-attr">h</span>=<span class="hljs-string">"6.4rem"</span>
                  <span class="hljs-attr">w</span>=<span class="hljs-string">"8rem"</span>
                  <span class="hljs-attr">bg</span>=<span class="hljs-string">"whiteAlpha.50"</span>
                  <span class="hljs-attr">src</span>=<span class="hljs-string">"/secondary.avif"</span>
                  <span class="hljs-attr">objectFit</span>=<span class="hljs-string">"cover"</span>
                  <span class="hljs-attr">rounded</span>=<span class="hljs-string">"xl"</span>
                  <span class="hljs-attr">cursor</span>=<span class="hljs-string">"pointer"</span>
                  <span class="hljs-attr">alt</span>=<span class="hljs-string">"Beverage Can"</span>
                /&gt;</span>
              <span class="hljs-tag">&lt;/<span class="hljs-name">Stack</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">HStack</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">MenuItem</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">MenuItem</span> <span class="hljs-attr">item</span>=<span class="hljs-string">"Title Two"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">Stack</span> <span class="hljs-attr">spacing</span>=<span class="hljs-string">{1}</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">Link</span> <span class="hljs-attr">color</span>=<span class="hljs-string">"gray.600"</span>&gt;</span>Link One<span class="hljs-tag">&lt;/<span class="hljs-name">Link</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">Link</span> <span class="hljs-attr">color</span>=<span class="hljs-string">"gray.600"</span>&gt;</span>Link Two<span class="hljs-tag">&lt;/<span class="hljs-name">Link</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">Link</span> <span class="hljs-attr">color</span>=<span class="hljs-string">"gray.600"</span>&gt;</span>Link Three<span class="hljs-tag">&lt;/<span class="hljs-name">Link</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">Link</span> <span class="hljs-attr">color</span>=<span class="hljs-string">"gray.600"</span>&gt;</span>Link Four<span class="hljs-tag">&lt;/<span class="hljs-name">Link</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">Stack</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">MenuItem</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">MenuItem</span> <span class="hljs-attr">item</span>=<span class="hljs-string">"Title Three"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">Stack</span> <span class="hljs-attr">spacing</span>=<span class="hljs-string">{1}</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">Link</span> <span class="hljs-attr">color</span>=<span class="hljs-string">"gray.600"</span>&gt;</span>Link One<span class="hljs-tag">&lt;/<span class="hljs-name">Link</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">Link</span> <span class="hljs-attr">color</span>=<span class="hljs-string">"gray.600"</span>&gt;</span>Link Two<span class="hljs-tag">&lt;/<span class="hljs-name">Link</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">Link</span> <span class="hljs-attr">color</span>=<span class="hljs-string">"gray.600"</span>&gt;</span>Link Three<span class="hljs-tag">&lt;/<span class="hljs-name">Link</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">Link</span> <span class="hljs-attr">color</span>=<span class="hljs-string">"gray.600"</span>&gt;</span>Link Four<span class="hljs-tag">&lt;/<span class="hljs-name">Link</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">Stack</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">MenuItem</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">Menu</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">Center</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<h2 id="heading-conclusion"><strong>Conclusion</strong></h2>
<p>That's all I have for you! Hopefully, you learned something new.</p>
<p>If you enjoyed this article, give it a ❤️ so others can find it too.</p>
<p>For more such content, stay in touch.</p>
<p>Contact Me:</p>
<p><a target="_blank" href="http://chetanverma.com/"><strong>Portfolio</strong></a> | <a target="_blank" href="https://github.com/chetanverma16"><strong>Github</strong></a> | <a target="_blank" href="https://www.linkedin.com/in/chetanverma7/"><strong>LinkedIn</strong></a> | <a target="_blank" href="https://twitter.com/chetanvermaaa"><strong>Twitter</strong></a></p>
]]></content:encoded></item><item><title><![CDATA[How To Create an Awesome Blob With React Three Fiber]]></title><description><![CDATA[Here is the video for this tutorial -
https://youtu.be/6YJ-2MvDqhc
 
Introduction
Hey everyone, in this post we will create a blob with react three fiber.
In this blog, we will use Next.js but you can follow this for any React Project.
So to get star...]]></description><link>https://blog.chetanverma.com/how-to-create-an-awesome-blob-with-react-three-fiber</link><guid isPermaLink="true">https://blog.chetanverma.com/how-to-create-an-awesome-blob-with-react-three-fiber</guid><category><![CDATA[React]]></category><category><![CDATA[Next.js]]></category><category><![CDATA[ThreeJS]]></category><category><![CDATA[how-to]]></category><category><![CDATA[Tutorial]]></category><dc:creator><![CDATA[Chetan verma]]></dc:creator><pubDate>Tue, 13 Dec 2022 07:37:12 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1670916871061/uupeUV-SE.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-here-is-the-video-for-this-tutorial"><strong>Here is the video for this tutorial -</strong></h2>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/6YJ-2MvDqhc">https://youtu.be/6YJ-2MvDqhc</a></div>
<p> </p>
<h3 id="heading-introduction">Introduction</h3>
<p>Hey everyone, in this post we will create a blob with react three fiber.</p>
<p>In this blog, we will use Next.js but you can follow this for any React Project.</p>
<p>So to get started with that we need to set up a <a target="_blank" href="https://nextjs.org/"><strong>Next.js</strong></a> app with <a target="_blank" href="https://docs.pmnd.rs/react-three-fiber/getting-started/introduction">React Three Fiber</a><strong>.</strong></p>
<p>in your terminal run these commands -</p>
<pre><code class="lang-bash">npx create-next-app my-project
<span class="hljs-built_in">cd</span> my-project
</code></pre>
<p>So once we have our next app ready.</p>
<p>we are going to add some bare-bone styles to it.</p>
<p>therefore, go to your <code>styles/globals.css</code> and add the CSS properties.</p>
<pre><code class="lang-scss"><span class="hljs-selector-class">.container</span> {
  <span class="hljs-attribute">position</span>: relative;
  <span class="hljs-attribute">display</span>: flex;
  <span class="hljs-attribute">align-items</span>: center;
  <span class="hljs-attribute">justify-content</span>: center;
  <span class="hljs-attribute">height</span>: <span class="hljs-number">100vh</span>;
  <span class="hljs-attribute">width</span>: <span class="hljs-number">100vw</span>;
  <span class="hljs-attribute">overflow</span>: hidden;
  <span class="hljs-attribute">font-family</span>: <span class="hljs-string">"Montserrat"</span>, sans-serif;
}

<span class="hljs-selector-tag">canvas</span> {
  <span class="hljs-attribute">position</span>: fixed;
  <span class="hljs-attribute">top</span>: <span class="hljs-number">0</span>;
  <span class="hljs-attribute">left</span>: <span class="hljs-number">0</span>;
  <span class="hljs-attribute">z-index</span>: -<span class="hljs-number">1</span>;
  <span class="hljs-attribute">height</span>: <span class="hljs-number">100vh</span>;
  <span class="hljs-attribute">width</span>: <span class="hljs-number">100vw</span>;
}
</code></pre>
<p>Now that we have our basic styling done let's go to our <code>pages/index.js</code> and add <code>Canvas</code> with <code>camera</code> attribute and set it to <code>[0.0,0.0,8.0]</code>.</p>
<p><code>pages/index.js</code></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { Canvas } <span class="hljs-keyword">from</span> <span class="hljs-string">"@react-three/fiber"</span>;
<span class="hljs-keyword">import</span> Blob <span class="hljs-keyword">from</span> <span class="hljs-string">"../components/Blob"</span>;

<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">Home</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"container"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Canvas</span> <span class="hljs-attr">camera</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">position:</span> [<span class="hljs-attr">0.0</span>, <span class="hljs-attr">0.0</span>, <span class="hljs-attr">8.0</span>] }}&gt;</span>

      <span class="hljs-tag">&lt;/<span class="hljs-name">Canvas</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>Now that we have our <code>canvas</code> ready we can now add our blob to it.</p>
<h3 id="heading-creating-blob-mesh">Creating Blob Mesh</h3>
<p>Before Creating Our Mesh Let's Understand what meshes are in <code>threejs</code> or <code>react-three-fiber</code></p>
<p><strong>Mesh</strong> - a mesh is a 3D Object which is made up of <code>Geometry</code> and <code>Material</code></p>
<p>Therefore,</p>
<p><strong>Mesh</strong> - Geometry + Material</p>
<ul>
<li><p><strong>Geometry</strong> is what defines the shape of the Mesh.</p>
</li>
<li><p>The <strong>Material</strong> defines how the object looks and also what gives it some specific properties like reflection, metalness, roughness, etc.</p>
</li>
</ul>
<p>Now that we know what are <strong>meshes</strong> let's create one.</p>
<p>so go to your <code>src</code> and create a new folder called <code>components</code></p>
<p>and under <code>components</code> folder, we are going to create our <code>Blob</code> folder which will contain all the files related to it.</p>
<p><code>components/Blob/index.js</code></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React, { useRef } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">const</span> Blob = <span class="hljs-function">() =&gt;</span> {
<span class="hljs-comment">// reference for mesh</span>
  <span class="hljs-keyword">const</span> mesh = useRef();

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">mesh</span>
      <span class="hljs-attr">ref</span>=<span class="hljs-string">{mesh}</span>
      <span class="hljs-attr">scale</span>=<span class="hljs-string">{1.5}</span>
      <span class="hljs-attr">position</span>=<span class="hljs-string">{[0,</span> <span class="hljs-attr">0</span>, <span class="hljs-attr">0</span>]}
    &gt;</span>
// Mesh - Geometry + Material
// Geometry
      <span class="hljs-tag">&lt;<span class="hljs-name">icosahedronBufferGeometry</span> <span class="hljs-attr">args</span>=<span class="hljs-string">{[2,</span> <span class="hljs-attr">20</span>]} /&gt;</span>
// Material
      <span class="hljs-tag">&lt;<span class="hljs-name">meshStandardMaterial</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">mesh</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Blob;
</code></pre>
<p>and let's add this back to our <code>canvas</code>.</p>
<pre><code class="lang-javascript">    &lt;Canvas camera={{ <span class="hljs-attr">position</span>: [<span class="hljs-number">0.0</span>, <span class="hljs-number">0.0</span>, <span class="hljs-number">8.0</span>] }}&gt;
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Blob</span> /&gt;</span></span>
    &lt;/Canvas&gt;
</code></pre>
<p>we will have our mesh look like this on the screen -</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1670873503831/iWho8j_8v.png" alt="Mesh Basic" class="image--center mx-auto" /></p>
<p>Yeah, it doesn't look like our blob yet for that we need to learn one more concept which is a <strong>shader</strong>.</p>
<h3 id="heading-what-is-a-shader">What is a <strong>Shader -</strong></h3>
<p>A shader is a <strong>program</strong>, written in <a target="_blank" href="https://www.khronos.org/opengl/wiki/Core_Language_(GLSL)"><strong>GLSL</strong></a>, that runs on the GPU. This program consists of two main functions that can output both 2D and 3D content:</p>
<p>and those two main functions are -</p>
<ul>
<li><p><strong>Vertex Shader</strong></p>
</li>
<li><p><strong>Fragment Shader</strong></p>
</li>
</ul>
<p>Let's learn about those ones by one, and then we will create our custom shader.</p>
<h3 id="heading-vertex-shader">Vertex Shader -</h3>
<p>The role of the vertex shader is to <strong>position each vertex</strong> of a geometry.<br />In simpler terms, this shader function allows you to programmatically alter the shape of your geometry and, potentially animate them.</p>
<h3 id="heading-fragment-shader">Fragment Shader -</h3>
<p>The role of the Fragment Shader is to <strong>set the color of each visible pixel</strong> of a geometry.</p>
<p>and when we combine <code>vertex</code> and <code>fragment</code> shader we get a totally new <strong>Material</strong>.</p>
<p>let's create our custom shader for our <code>Blob</code></p>
<h3 id="heading-creating-custom-shader">Creating Custom Shader</h3>
<p>In our <code>Blob</code> component replace <code>&lt;meshStandardMaterial /&gt;</code> with <code>&lt;shaderMaterial/&gt;</code> , and pass in two functions <code>vertexShader</code> and <code>fragmentShader</code> this will create our custom <strong>shader</strong> material.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React, { useMemo, useRef } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> vertexShader <span class="hljs-keyword">from</span> <span class="hljs-string">"./vertexShader"</span>;
<span class="hljs-keyword">import</span> fragmentShader <span class="hljs-keyword">from</span> <span class="hljs-string">"./fragmentShader"</span>;

<span class="hljs-keyword">const</span> Blob = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> mesh = useRef();

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">mesh</span>
      <span class="hljs-attr">ref</span>=<span class="hljs-string">{mesh}</span>
      <span class="hljs-attr">scale</span>=<span class="hljs-string">{1.5}</span>
      <span class="hljs-attr">position</span>=<span class="hljs-string">{[0,</span> <span class="hljs-attr">0</span>, <span class="hljs-attr">0</span>]}
    &gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">icosahedronBufferGeometry</span> <span class="hljs-attr">args</span>=<span class="hljs-string">{[2,</span> <span class="hljs-attr">20</span>]} /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">shaderMaterial</span>
        <span class="hljs-attr">vertexShader</span>=<span class="hljs-string">{vertexShader}</span>
        <span class="hljs-attr">fragmentShader</span>=<span class="hljs-string">{fragmentShader}</span>
      /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">mesh</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Blob;
</code></pre>
<p>now let's add some GLSL to our <strong>shader</strong>.</p>
<p>now create a new file under <code>components/Blob/vertexShader.js</code></p>
<p><code>vertexShader.js</code> -</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> vertexShader = <span class="hljs-string">`
uniform float u_intensity;
uniform float u_time;

varying vec2 vUv;
varying float vDisplacement

void main() {
      vUv = uv;
    vec3 newPosition = position + normal * vec3(u_intensity * sin(position.y * 10.0 + u_time));
    vDisplacement = sin(position.y * 10.0 + u_time);
    gl_Position = projectionMatrix * modelViewMatrix * vec4(newPosition, 1.0);
}
`</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> vertexShader;
</code></pre>
<ul>
<li><p>you can see some variables defined with <code>uniform</code> and <code>varying</code> prefixes we will learn about those later in this post.</p>
</li>
<li><p>this function runs for every vertex and sets a property called <code>gl_Position</code> that contains the x,y, and z coordinates of a given vertex on the screen.</p>
</li>
</ul>
<p>Now we have our <code>vertexShader</code> function let's add <code>fragmentShader</code> function to complete our <code>shaderMaterial</code>.</p>
<p><code>fragmentShader.js</code></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> fragmentShader = <span class="hljs-string">`
uniform float u_intensity;
uniform float u_time;

varying vec2 vUv;
varying float vDisplacement;

void main() {
    float distort = 2.0 * vDisplacement * u_intensity * sin(vUv.y * 10.0 + u_time);
// this defines our gradient
    vec3 color = vec3(abs(vUv - 0.5) * 2.0  * (1.0 - distort), 1.0);
    gl_FragColor = vec4(color, 1.0);
}

`</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> fragmentShader;
</code></pre>
<ul>
<li><p>Similarly, here we have a <code>uniform</code> and <code>varying</code> variables.</p>
</li>
<li><p>this function runs for each pixel and sets the color of that pixel and the variable which is responsible for that is <code>gl_FragColor</code> which is a <code>vec4</code> .</p>
</li>
</ul>
<p>after defining those let's see what we have on our screen.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1670874748127/VkYDHlioj.png" alt class="image--center mx-auto" /></p>
<p>Great, we have our blob with <code>gradient</code> .</p>
<p>now we just need to animate it and then we will have our <code>Blob</code> ready.</p>
<p>Let's do that.</p>
<h3 id="heading-animating-our-blob">Animating Our Blob.</h3>
<p>To animate our Blob we need to understand what are <code>uniforms</code> and <code>varying</code></p>
<p><code>Uniforms</code> - To pass data from your Javascript code into your shader, we need to use <strong>uniforms</strong>. A uniform acts as an input to <em>both</em> vertex and fragment shader.</p>
<p><code>Varyings</code> - A varying is <strong>a variable that can be declared and set in the vertex shader to be read by the fragment shader</strong>.</p>
<p>ok so now we know what are <code>uniforms</code> and <code>varyings</code> let's use this knowledge to animate our <code>Blob</code>.</p>
<p>so, in our <code>Blob</code> let's create a new <code>memoized</code> value using <code>useMemo</code> and name it <code>uniforms</code> and under that, we are going to add an object with the property <code>u_time</code> and <code>u_intesity</code> which we have already defined in our vertex and fragment shader functions.</p>
<pre><code class="lang-javascript">  <span class="hljs-keyword">const</span> uniforms = useMemo(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">return</span> {
      <span class="hljs-attr">u_time</span>: { <span class="hljs-attr">value</span>: <span class="hljs-number">0</span> },
      <span class="hljs-attr">u_intensity</span>: { <span class="hljs-attr">value</span>: <span class="hljs-number">0.3</span> },
    };
  });
</code></pre>
<p>and now let's pass our <code>uniforms</code> to our <code>shaderMaterial</code></p>
<pre><code class="lang-javascript"> &lt;shaderMaterial
        vertexShader={vertexShader}
        fragmentShader={fragmentShader}
        uniforms={uniforms}
      /&gt;
</code></pre>
<p><strong>Perlin Noise</strong> -</p>
<p>now we have our uniforms passed to our <code>shaderMaterial</code>, but to have an animation behave like an <code>BLOB</code> animation we need to use something called <code>perlin noises</code> .</p>
<p>let's add our <code>perlin noise</code> to our <code>vertexShader</code></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> vertexShader = <span class="hljs-string">`
uniform float u_intensity;
uniform float u_time;

varying vec2 vUv;
varying float vDisplacement;

// Classic Perlin 3D Noise 
// by Stefan Gustavson
//
vec4 permute(vec4 x) {
    return mod(((x*34.0)+1.0)*x, 289.0);
}

vec4 taylorInvSqrt(vec4 r) {
    return 1.79284291400159 - 0.85373472095314 * r;
}

vec3 fade(vec3 t) {
    return t*t*t*(t*(t*6.0-15.0)+10.0);
}

float cnoise(vec3 P) {
    vec3 Pi0 = floor(P); // Integer part for indexing
    vec3 Pi1 = Pi0 + vec3(1.0); // Integer part + 1
    Pi0 = mod(Pi0, 289.0);
    Pi1 = mod(Pi1, 289.0);
    vec3 Pf0 = fract(P); // Fractional part for interpolation
    vec3 Pf1 = Pf0 - vec3(1.0); // Fractional part - 1.0
    vec4 ix = vec4(Pi0.x, Pi1.x, Pi0.x, Pi1.x);
    vec4 iy = vec4(Pi0.yy, Pi1.yy);
    vec4 iz0 = Pi0.zzzz;
    vec4 iz1 = Pi1.zzzz;

    vec4 ixy = permute(permute(ix) + iy);
    vec4 ixy0 = permute(ixy + iz0);
    vec4 ixy1 = permute(ixy + iz1);

    vec4 gx0 = ixy0 / 7.0;
    vec4 gy0 = fract(floor(gx0) / 7.0) - 0.5;
    gx0 = fract(gx0);
    vec4 gz0 = vec4(0.5) - abs(gx0) - abs(gy0);
    vec4 sz0 = step(gz0, vec4(0.0));
    gx0 -= sz0 * (step(0.0, gx0) - 0.5);
    gy0 -= sz0 * (step(0.0, gy0) - 0.5);

    vec4 gx1 = ixy1 / 7.0;
    vec4 gy1 = fract(floor(gx1) / 7.0) - 0.5;
    gx1 = fract(gx1);
    vec4 gz1 = vec4(0.5) - abs(gx1) - abs(gy1);
    vec4 sz1 = step(gz1, vec4(0.0));
    gx1 -= sz1 * (step(0.0, gx1) - 0.5);
    gy1 -= sz1 * (step(0.0, gy1) - 0.5);

    vec3 g000 = vec3(gx0.x,gy0.x,gz0.x);
    vec3 g100 = vec3(gx0.y,gy0.y,gz0.y);
    vec3 g010 = vec3(gx0.z,gy0.z,gz0.z);
    vec3 g110 = vec3(gx0.w,gy0.w,gz0.w);
    vec3 g001 = vec3(gx1.x,gy1.x,gz1.x);
    vec3 g101 = vec3(gx1.y,gy1.y,gz1.y);
    vec3 g011 = vec3(gx1.z,gy1.z,gz1.z);
    vec3 g111 = vec3(gx1.w,gy1.w,gz1.w);

    vec4 norm0 = taylorInvSqrt(vec4(dot(g000, g000), dot(g010, g010), dot(g100, g100), dot(g110, g110)));
    g000 *= norm0.x;
    g010 *= norm0.y;
    g100 *= norm0.z;
    g110 *= norm0.w;
    vec4 norm1 = taylorInvSqrt(vec4(dot(g001, g001), dot(g011, g011), dot(g101, g101), dot(g111, g111)));
    g001 *= norm1.x;
    g011 *= norm1.y;
    g101 *= norm1.z;
    g111 *= norm1.w;

    float n000 = dot(g000, Pf0);
    float n100 = dot(g100, vec3(Pf1.x, Pf0.yz));
    float n010 = dot(g010, vec3(Pf0.x, Pf1.y, Pf0.z));
    float n110 = dot(g110, vec3(Pf1.xy, Pf0.z));
    float n001 = dot(g001, vec3(Pf0.xy, Pf1.z));
    float n101 = dot(g101, vec3(Pf1.x, Pf0.y, Pf1.z));
    float n011 = dot(g011, vec3(Pf0.x, Pf1.yz));
    float n111 = dot(g111, Pf1);

    vec3 fade_xyz = fade(Pf0);
    vec4 n_z = mix(vec4(n000, n100, n010, n110), vec4(n001, n101, n011, n111), fade_xyz.z);
    vec2 n_yz = mix(n_z.xy, n_z.zw, fade_xyz.y);
    float n_xyz = mix(n_yz.x, n_yz.y, fade_xyz.x); 
    return 2.2 * n_xyz;
}

// End of Perlin Noise Code


void main() {
    vUv = uv;

    vDisplacement = cnoise(position + vec3(2.0 * u_time));

    vec3 newPosition = position + normal * (u_intensity * vDisplacement);

    vec4 modelPosition = modelMatrix * vec4(newPosition, 1.0);
    vec4 viewPosition = viewMatrix * modelPosition;
    vec4 projectedPosition = projectionMatrix * viewPosition;

    gl_Position = projectedPosition;
}
`</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> vertexShader;
</code></pre>
<p>now let's add <code>useFrame</code> the function provided <code>@react-three/fiber</code> to change our uniform variables based on each frame, which will result in our blob animating.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React, { useMemo, useRef } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> vertexShader <span class="hljs-keyword">from</span> <span class="hljs-string">"./vertexShader"</span>;
<span class="hljs-keyword">import</span> fragmentShader <span class="hljs-keyword">from</span> <span class="hljs-string">"./fragmentShader"</span>;
<span class="hljs-keyword">import</span> { useFrame } <span class="hljs-keyword">from</span> <span class="hljs-string">"@react-three/fiber"</span>;
<span class="hljs-keyword">import</span> { MathUtils } <span class="hljs-keyword">from</span> <span class="hljs-string">"three"</span>;

<span class="hljs-keyword">const</span> Blob = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> mesh = useRef();
  <span class="hljs-keyword">const</span> uniforms = useMemo(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">return</span> {
      <span class="hljs-attr">u_time</span>: { <span class="hljs-attr">value</span>: <span class="hljs-number">0</span> },
      <span class="hljs-attr">u_intensity</span>: { <span class="hljs-attr">value</span>: <span class="hljs-number">0.3</span> },
    };
  });

  useFrame(<span class="hljs-function">(<span class="hljs-params">state</span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> { clock } = state;
    <span class="hljs-keyword">if</span> (mesh.current) {
      mesh.current.material.uniforms.u_time.value =
        <span class="hljs-number">0.4</span> * clock.getElapsedTime();

      mesh.current.material.uniforms.u_intensity.value = MathUtils.lerp(
        mesh.current.material.uniforms.u_intensity.value,
       <span class="hljs-number">0.15</span>,
        <span class="hljs-number">0.02</span>
      );
    }
  });
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">mesh</span>
      <span class="hljs-attr">ref</span>=<span class="hljs-string">{mesh}</span>
      <span class="hljs-attr">scale</span>=<span class="hljs-string">{1.5}</span>
      <span class="hljs-attr">position</span>=<span class="hljs-string">{[0,</span> <span class="hljs-attr">0</span>, <span class="hljs-attr">0</span>]}
    &gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">icosahedronBufferGeometry</span> <span class="hljs-attr">args</span>=<span class="hljs-string">{[2,</span> <span class="hljs-attr">20</span>]} /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">shaderMaterial</span>
        <span class="hljs-attr">vertexShader</span>=<span class="hljs-string">{vertexShader}</span>
        <span class="hljs-attr">fragmentShader</span>=<span class="hljs-string">{fragmentShader}</span>
        <span class="hljs-attr">uniforms</span>=<span class="hljs-string">{uniforms}</span>
      /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">mesh</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Blob;
</code></pre>
<p>and now, we will have our blob animating -</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1670875933861/Pk9Uz8wsk.gif" alt class="image--center mx-auto" /></p>
<h2 id="heading-conclusion"><strong>Conclusion</strong></h2>
<p>That's all I have for you! Hopefully, you learned something new.</p>
<p>If you enjoyed this article, give it a ❤️ so others can find it too.</p>
<p>For more such content, stay in touch on Twitter</p>
<p>Contact Me:</p>
<p><a target="_blank" href="http://chetanverma.com/"><strong>Portfolio</strong></a> | <a target="_blank" href="https://github.com/chetanverma16"><strong>Github</strong></a> | <a target="_blank" href="https://www.linkedin.com/in/chetanverma7/"><strong>LinkedIn</strong></a> | <a target="_blank" href="https://twitter.com/chetanvermaaa">Twitter</a></p>
]]></content:encoded></item><item><title><![CDATA[React State Management Very Quickly With Zustand]]></title><description><![CDATA[https://youtu.be/du-OzGQlmeA
 
Introduction
Hey Everybody, In this tutorial, we are going the implement Zustand which is an amazing React State Management Library.
Preview of what we are going to create in this tutorial -

Initial Setup
So, to get st...]]></description><link>https://blog.chetanverma.com/react-state-management-very-quickly-with-zustand</link><guid isPermaLink="true">https://blog.chetanverma.com/react-state-management-very-quickly-with-zustand</guid><category><![CDATA[React]]></category><category><![CDATA[zustand]]></category><category><![CDATA[Tutorial]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[Next.js]]></category><dc:creator><![CDATA[Chetan verma]]></dc:creator><pubDate>Thu, 01 Sep 2022 23:36:32 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1662073990315/D6jT-MuLa.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/du-OzGQlmeA">https://youtu.be/du-OzGQlmeA</a></div>
<p> </p>
<h2 id="heading-introduction">Introduction</h2>
<p>Hey Everybody, In this tutorial, we are going the implement Zustand which is an amazing React State Management Library.</p>
<p>Preview of what we are going to create in this tutorial -</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1662071156019/IC-HINOxZ.png" alt="Screenshot 2022-09-02 at 3.55.49 AM.png" /></p>
<h2 id="heading-initial-setup">Initial Setup</h2>
<p>So, to get started with this tutorial we are going to do some initial setup, which is a Next.js app with TailwindCSS &amp; NextUI.</p>
<p>so let's create our Next.js app.</p>
<p><code>npx create-next-app your-project-name</code></p>
<p>then we are going to cd into our project, and then we are going to install tailwindCSS</p>
<p>you can follow this installation guide for installing TailwindCSS in your project. Installation Guide - https://tailwindcss.com/docs/guides/nextjs</p>
<p>So, once we have our TailwindCSS Setup.</p>
<p>Let's Install NextUI with this command: <code>npm install @nextui-org/react</code></p>
<p>Ok, now we have everything that we need to follow along with this tutorial.</p>
<p>let's go to the <code>index.js</code> of our app, and create some UI for our app.</p>
<p><code>Index.js</code></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { Button, Input, Card } <span class="hljs-keyword">from</span> <span class="hljs-string">"@nextui-org/react"</span>;
<span class="hljs-keyword">import</span> {useState} <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;

<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">Home</span>(<span class="hljs-params"></span>) </span>{
 <span class="hljs-keyword">const</span> [newtodo, setNewTodo] = useState(<span class="hljs-string">""</span>);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"container text-black mx-auto flex flex-col items-center p-28"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"w-full"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-3xl"</span>&gt;</span>Todo<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"mt-2 flex items-center w-full"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Input</span>
          <span class="hljs-attr">value</span>=<span class="hljs-string">{newtodo}</span>
          <span class="hljs-attr">onChange</span>=<span class="hljs-string">{(e)</span> =&gt;</span> setNewTodo(e.target.value)}
          fullWidth
          placeholder="Enter TODO"
          clearable
        /&gt;
        <span class="hljs-tag">&lt;<span class="hljs-name">Button</span> <span class="hljs-attr">shadow</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"m-2"</span>&gt;</span>
          ADD
        <span class="hljs-tag">&lt;/<span class="hljs-name">Button</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"mt-5 w-full flex items-center"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Card</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"w-full"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">Card.Body</span>&gt;</span>Todo One<span class="hljs-tag">&lt;/<span class="hljs-name">Card.Body</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">Card</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Button</span>
            <span class="hljs-attr">size</span>=<span class="hljs-string">"lg"</span>
            <span class="hljs-attr">shadow</span>
            <span class="hljs-attr">auto</span>
            <span class="hljs-attr">color</span>=<span class="hljs-string">"error"</span>
            <span class="hljs-attr">className</span>=<span class="hljs-string">"m-2"</span>
          &gt;</span>
            Delete
          <span class="hljs-tag">&lt;/<span class="hljs-name">Button</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>We will have something like this on the screen -</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1662071397213/fVzZ5SDJ5.png" alt="Screenshot 2022-09-02 at 3.59.50 AM.png" /></p>
<h2 id="heading-implementing-zustand">Implementing Zustand</h2>
<p>Let's add Zustand to our app now, to do that we need to create <code>store.js</code> inside our app.</p>
<p>In our store we are going to have three things</p>
<p><code>todos:[]</code>: this array will help us in keeping track of all the todos and help us in rendering the todos.</p>
<p><code>addTodo</code>: <code>addTodo</code> will help us in adding a new todo to our todos array, it takes in a <code>todo</code> as an argument, spread the previous state(<code>...state.todos</code>), and add the new <code>todo</code> at the end.</p>
<p><code>removeTodo</code>: this function will help us in deleting a particular <code>todo</code> with the provided index.</p>
<p>here is the code for our <code>store.js</code> -</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> create <span class="hljs-keyword">from</span> <span class="hljs-string">"zustand"</span>;

<span class="hljs-keyword">const</span> useStore = create(<span class="hljs-function">(<span class="hljs-params">set</span>) =&gt;</span> ({
  <span class="hljs-attr">todos</span>: [],
  <span class="hljs-attr">todo</span>: <span class="hljs-string">""</span>,
  <span class="hljs-attr">addTodo</span>: <span class="hljs-function">(<span class="hljs-params">todo</span>) =&gt;</span> set(<span class="hljs-function">(<span class="hljs-params">state</span>) =&gt;</span> ({ <span class="hljs-attr">todos</span>: [...state.todos, todo] })),
  <span class="hljs-attr">removeTodo</span>: <span class="hljs-function">(<span class="hljs-params">index</span>) =&gt;</span>
    set(<span class="hljs-function">(<span class="hljs-params">state</span>) =&gt;</span> ({ <span class="hljs-attr">todos</span>: state.todos.filter(<span class="hljs-function">(<span class="hljs-params">_, i</span>) =&gt;</span> i !== index) })),
}));

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> useStore;
</code></pre>
<p>Ok, so now we have our store. Let's bind everything up and use it in our app.</p>
<p>go back to <code>index.js</code>-</p>
<p>and import <code>useStore</code> from "../store.js`</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> useStore <span class="hljs-keyword">from</span> <span class="hljs-string">"../store"</span>;
</code></pre>
<p>ok so now we have our store imported let's get our current <code>todos</code>, and functions for handling all the logic.</p>
<pre><code class="lang-javascript">
  <span class="hljs-keyword">const</span> todos = useStore(<span class="hljs-function">(<span class="hljs-params">state</span>) =&gt;</span> state.todos);
  <span class="hljs-keyword">const</span> addTodo = useStore(<span class="hljs-function">(<span class="hljs-params">state</span>) =&gt;</span> state.addTodo);
  <span class="hljs-keyword">const</span> removeTodo = useStore(<span class="hljs-function">(<span class="hljs-params">state</span>) =&gt;</span> state.removeTodo);
</code></pre>
<p>Let's connect everything up and see if everything works or not.</p>
<p><code>index.js</code> -</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { Button, Input, Card } <span class="hljs-keyword">from</span> <span class="hljs-string">"@nextui-org/react"</span>;
<span class="hljs-keyword">import</span> { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> useStore <span class="hljs-keyword">from</span> <span class="hljs-string">"../store"</span>;
<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">Home</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [newtodo, setNewTodo] = useState(<span class="hljs-string">""</span>);

  <span class="hljs-keyword">const</span> todos = useStore(<span class="hljs-function">(<span class="hljs-params">state</span>) =&gt;</span> state.todos);
  <span class="hljs-keyword">const</span> addTodo = useStore(<span class="hljs-function">(<span class="hljs-params">state</span>) =&gt;</span> state.addTodo);
  <span class="hljs-keyword">const</span> removeTodo = useStore(<span class="hljs-function">(<span class="hljs-params">state</span>) =&gt;</span> state.removeTodo);

<span class="hljs-comment">// this function will check if the input is valid or not</span>
  <span class="hljs-keyword">const</span> AddNewTodo = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">if</span> (newtodo.length &gt; <span class="hljs-number">0</span>) {
      addTodo(newtodo);
      setNewTodo(<span class="hljs-string">""</span>);
    }
  };


  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"container text-black mx-auto flex flex-col items-center p-28"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"w-full"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-3xl"</span>&gt;</span>Todo<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"mt-2 flex items-center w-full"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Input</span>
          <span class="hljs-attr">value</span>=<span class="hljs-string">{newtodo}</span>
          <span class="hljs-attr">onChange</span>=<span class="hljs-string">{(e)</span> =&gt;</span> setNewTodo(e.target.value)}
          fullWidth
          placeholder="Enter TODO"
          clearable
        &gt;<span class="hljs-tag">&lt;/<span class="hljs-name">Input</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{AddNewTodo}</span> <span class="hljs-attr">shadow</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"m-2"</span>&gt;</span>
          ADD
        <span class="hljs-tag">&lt;/<span class="hljs-name">Button</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

// Map all the current Todos
      {todos.map((todo, index) =&gt; (
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{index}</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"mt-5 w-full flex items-center"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Card</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"w-full"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">Card.Body</span>&gt;</span>{todo}<span class="hljs-tag">&lt;/<span class="hljs-name">Card.Body</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">Card</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Button</span>
            <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> removeTodo(index)}
            size="lg"
            shadow
            auto
            color="error"
            className="m-2"
          &gt;
            Delete
          <span class="hljs-tag">&lt;/<span class="hljs-name">Button</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      ))}
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>After connecting all the things up, we will be able to create new todo and delete todo.</p>
<p>AWESOME!</p>
<p>now we have Zustand Working on our app.</p>
<h2 id="heading-bonus">Bonus</h2>
<p>This part of our app is completely optional. you can go through this if you want to discover a cool animation library that will help you add animation with just 3 lines of code.</p>
<p>Let's begin,</p>
<p>so we want to make our to-do app more amazing by adding some cool animation to it. to do that we are going to use <code>auto-animate</code>, it is an amazing animation library from <a target="_blank" href="https://formkit.com/"><strong>formkit</strong></a>.</p>
<p>we are going to import <code>useEffect</code>, <code>useRef</code> from <code>react</code> &amp; <code>auto-animate</code> from <code>@formkit/auto-animate</code>.</p>
<p>after importing these,</p>
<p>create a ref with any name, I am calling it <strong>parent</strong>.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> parent = useRef(<span class="hljs-literal">null</span>);
</code></pre>
<p>after That in our <code>useEffect</code> hook we are going to add <code>parent</code> as a dependency and pass <code>parent.current</code> to <code>autoAnimate</code></p>
<pre><code class="lang-javascript">  useEffect(<span class="hljs-function">() =&gt;</span> {
    parent.current &amp;&amp; autoAnimate(parent.current);
  }, [parent]);
</code></pre>
<p>ok, so the last thing we need to do is to add the ref to our parent element.</p>
<p>this is how our whole code will look like -</p>
<p><code>index.js</code></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { Button, Input, Card } <span class="hljs-keyword">from</span> <span class="hljs-string">"@nextui-org/react"</span>;
<span class="hljs-keyword">import</span> { useEffect, useState, useRef } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> useStore <span class="hljs-keyword">from</span> <span class="hljs-string">"../store"</span>;
<span class="hljs-keyword">import</span> autoAnimate <span class="hljs-keyword">from</span> <span class="hljs-string">"@formkit/auto-animate"</span>;
<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">Home</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> parent = useRef(<span class="hljs-literal">null</span>);
  <span class="hljs-keyword">const</span> [newtodo, setNewTodo] = useState(<span class="hljs-string">""</span>);
  <span class="hljs-keyword">const</span> todos = useStore(<span class="hljs-function">(<span class="hljs-params">state</span>) =&gt;</span> state.todos);
  <span class="hljs-keyword">const</span> addTodo = useStore(<span class="hljs-function">(<span class="hljs-params">state</span>) =&gt;</span> state.addTodo);
  <span class="hljs-keyword">const</span> removeTodo = useStore(<span class="hljs-function">(<span class="hljs-params">state</span>) =&gt;</span> state.removeTodo);

  <span class="hljs-keyword">const</span> AddNewTodo = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">if</span> (newtodo.length &gt; <span class="hljs-number">0</span>) {
      addTodo(newtodo);
      setNewTodo(<span class="hljs-string">""</span>);
    }
  };

  useEffect(<span class="hljs-function">() =&gt;</span> {
    parent.current &amp;&amp; autoAnimate(parent.current);
  }, [parent]);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>
      <span class="hljs-attr">className</span>=<span class="hljs-string">"container text-black mx-auto flex flex-col items-center p-28"</span>
// <span class="hljs-attr">here</span> <span class="hljs-attr">we</span> <span class="hljs-attr">are</span> <span class="hljs-attr">using</span> <span class="hljs-attr">our</span> <span class="hljs-attr">parent</span> <span class="hljs-attr">ref</span>
      <span class="hljs-attr">ref</span>=<span class="hljs-string">{parent}</span>
    &gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"w-full"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-3xl"</span>&gt;</span>Todo<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"mt-2 flex items-center w-full"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Input</span>
          <span class="hljs-attr">value</span>=<span class="hljs-string">{newtodo}</span>
          <span class="hljs-attr">onChange</span>=<span class="hljs-string">{(e)</span> =&gt;</span> setNewTodo(e.target.value)}
          fullWidth
          placeholder="Enter TODO"
          clearable
        &gt;<span class="hljs-tag">&lt;/<span class="hljs-name">Input</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{AddNewTodo}</span> <span class="hljs-attr">shadow</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"m-2"</span>&gt;</span>
          ADD
        <span class="hljs-tag">&lt;/<span class="hljs-name">Button</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      {todos.map((todo, index) =&gt; (
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{index}</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"mt-5 w-full flex items-center"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Card</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"w-full"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">Card.Body</span>&gt;</span>{todo}<span class="hljs-tag">&lt;/<span class="hljs-name">Card.Body</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">Card</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Button</span>
            <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> removeTodo(index)}
            size="lg"
            shadow
            auto
            color="error"
            className="m-2"
          &gt;
            Delete
          <span class="hljs-tag">&lt;/<span class="hljs-name">Button</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      ))}
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>Now, If you will try adding and removing todo, you will see some cool animations.</p>
<p>Github Repo -https://github.com/chetanverma16/Zustand-tutorial</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>That's all I have for you! Hopefully, you learned something new.</p>
<p>If you enjoyed this article, give it a ❤️ so others can find it too.</p>
<p>For more such content, stay in touch on Twitter</p>
<p>Contact Me:</p>
<p><a target="_blank" href="http://chetanverma.com/">Portfolio</a> | <a target="_blank" href="https://github.com/chetanverma16">Github</a> | <a target="_blank" href="https://www.linkedin.com/in/chetanverma7/">LinkedIn</a> | <a target="_blank" href="https://twitter.com/realchetanverma">Twitter</a></p>
]]></content:encoded></item><item><title><![CDATA[How To Create a Full Stack app with SolidJS, Supabase, and TailwindCSS]]></title><description><![CDATA[https://www.youtube.com/watch?v=LVw8AzCmhDQ
 
Introduction
Hey Everyone,In this tutorial, we are going to create a full stack Notes app with Solid.js and Supabase.
Let's get started
Setting Up Supabase

Go to https://app.supabase.com/

Click on New P...]]></description><link>https://blog.chetanverma.com/how-to-create-a-full-stack-app-with-solidjs-supabase-and-tailwindcss</link><guid isPermaLink="true">https://blog.chetanverma.com/how-to-create-a-full-stack-app-with-solidjs-supabase-and-tailwindcss</guid><category><![CDATA[Tutorial]]></category><category><![CDATA[supabase]]></category><category><![CDATA[solidjs]]></category><category><![CDATA[guide]]></category><category><![CDATA[full stack web development]]></category><dc:creator><![CDATA[Chetan verma]]></dc:creator><pubDate>Tue, 16 Aug 2022 10:04:08 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1660644042746/_AzhXrR_V.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.youtube.com/watch?v=LVw8AzCmhDQ">https://www.youtube.com/watch?v=LVw8AzCmhDQ</a></div>
<p> </p>
<h3 id="heading-introduction">Introduction</h3>
<p>Hey Everyone,<br />In this tutorial, we are going to create a full stack Notes app with Solid.js and Supabase.</p>
<p>Let's get started</p>
<h3 id="heading-setting-up-supabase">Setting Up Supabase</h3>
<ul>
<li><p>Go to <a target="_blank" href="https://app.supabase.com/">https://app.supabase.com/</a></p>
</li>
<li><p>Click on New Project.</p>
</li>
<li><p>After Filling in all the project details.</p>
</li>
<li><p>Click on Create</p>
</li>
</ul>
<h3 id="heading-installing-solid">Installing Solid</h3>
<p>Now, that we have our supabase app running let's create the frontend of our app. we are going to use <a target="_blank" href="https://www.solidjs.com/">Solid.js</a> in this app.</p>
<ul>
<li><p>To Create a Solid.js App We are going to use this command.<br />  <code>npx degit solidjs/templates/js solid-app</code></p>
</li>
<li><p>Now we are going to cd into<br />  <code>cd solid-app</code></p>
</li>
<li><p>After that, we are going to install all the dependencies, In this tutorial I will be using <code>yarn</code> but you are free to use <code>npm</code> or <code>pnpm</code>.  </p>
</li>
<li><p>Now Let's run and see what we have.<br />  <code>yarn dev</code></p>
</li>
</ul>
<p>you will have your <code>solid-app</code> running -</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1660131225505/nvuyuZbYp.png" alt="Screenshot 2022-08-10 at 5.03.37 PM.png" /></p>
<p>Now we have everything running, let's add some packages which we are going to use to bring this app to life. I am a big fan of TailwindCSS, It helps me style my app pretty fast, I use it in every app. so let's do that.</p>
<ul>
<li><p>Run this command in your terminal.<br />  <code>yarn add tailwindcss@latest postcss@latest autoprefixer@latest --dev</code></p>
</li>
<li><p>Next, generate your tailwind.config.js and postcss.config.js files<br />  <code>npx tailwindcss init -p</code></p>
</li>
</ul>
<p>this command will create two files in your root directory: <code>tailwind.config.js</code> and <code>postcss.config.js</code>.</p>
<p>Now, Let's open the <code>tailwind.config.js</code> and update the <code>purge</code> property to include the path to our <code>src</code> folder and <code>index.html</code> file.</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">module</span>.exports = {
  <span class="hljs-attr">content</span>: [<span class="hljs-string">'./index.html'</span>, <span class="hljs-string">'./src/**/*.{js,ts,jsx,tsx}'</span>],
  <span class="hljs-attr">darkMode</span>: <span class="hljs-literal">false</span>, <span class="hljs-comment">// or 'media' or 'class'</span>
  <span class="hljs-attr">theme</span>: {
    <span class="hljs-attr">extend</span>: {},
  },
  <span class="hljs-attr">variants</span>: {
    <span class="hljs-attr">extend</span>: {},
  },
  <span class="hljs-attr">plugins</span>: [],
}
</code></pre>
<p>Now, we will add the Tailwind's style using the <code>@tailwind</code> directive within you main CSS file (<code>src/index.css</code>)</p>
<pre><code class="lang-javascript"><span class="hljs-comment">/* ./src/index.css */</span>
@tailwind base;
@tailwind components;
@tailwind utilities;
</code></pre>
<p>Now, we have <code>TailwindCSS</code> in our app.</p>
<ul>
<li>The next thing we need to add is <code>supabase-js</code><br />  <code>yarn add @supabase/supabase-js</code></li>
</ul>
<p>Now, after adding these let's add the environment variables</p>
<pre><code class="lang-javascript">VITE_SUPABASE_URL=YOUR_SUPABASE_URL
VITE_SUPABASE_ANON_KEY=YOUR_SUPABASE_ANON_KEY
</code></pre>
<p>at last, we need to create a Supabase Client which will help us in initializing the Supabase with our environment variables.</p>
<p><code>src/supabaseClient.jsx</code> -</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { createClient } <span class="hljs-keyword">from</span> <span class="hljs-string">'@supabase/supabase-js'</span>

<span class="hljs-keyword">const</span> supabaseUrl = <span class="hljs-keyword">import</span>.meta.env.VITE_SUPABASE_URL
<span class="hljs-keyword">const</span> supabaseAnonKey = <span class="hljs-keyword">import</span>.meta.env.VITE_SUPABASE_ANON_KEY

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> supabase = createClient(supabaseUrl, supabaseAnonKey)
</code></pre>
<h2 id="heading-authentication">Authentication</h2>
<p>let's start with adding authentication to our app,</p>
<p>we need to have different routes for different parts of our app, for example <code>/login</code> route will help us in handling authentication, and once authenticated we need to have the <code>dashboard</code> unlocked at <code>/</code> this route.</p>
<p>so to handle different routes we need to add <code>@solidjs/router</code>.</p>
<pre><code class="lang-javascript">yarn add @solidjs/router
</code></pre>
<p>once we have our router we need to create a new router with a new component under <code>components/login.jsx</code></p>
<p><code>components/login.jsx</code> -</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { createEffect, createSignal } <span class="hljs-keyword">from</span> <span class="hljs-string">"solid-js"</span>;
<span class="hljs-keyword">import</span> { supabase } <span class="hljs-keyword">from</span> <span class="hljs-string">"../supabaseClient"</span>;
<span class="hljs-keyword">import</span> Button <span class="hljs-keyword">from</span> <span class="hljs-string">"./button"</span>;
<span class="hljs-keyword">import</span> { useNavigate } <span class="hljs-keyword">from</span> <span class="hljs-string">"@solidjs/router"</span>;

<span class="hljs-keyword">const</span> Login = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> [email, setEmail] = createSignal(<span class="hljs-string">""</span>);
  <span class="hljs-keyword">const</span> [loading, setLoading] = createSignal(<span class="hljs-literal">false</span>);
  <span class="hljs-keyword">const</span> navigate = useNavigate();

  createEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">if</span> (supabase.auth.session()) {
      navigate(<span class="hljs-string">"/"</span>);
    }
  });

  <span class="hljs-keyword">const</span> handleLogin = <span class="hljs-keyword">async</span> (e) =&gt; {
    e.preventDefault();
    <span class="hljs-keyword">try</span> {
      setLoading(<span class="hljs-literal">true</span>);
      <span class="hljs-keyword">const</span> { error } = <span class="hljs-keyword">await</span> supabase.auth.signIn({ <span class="hljs-attr">email</span>: email() });
      <span class="hljs-keyword">if</span> (error) <span class="hljs-keyword">throw</span> error;
      alert(<span class="hljs-string">"Check your email for the login link!"</span>);
    } <span class="hljs-keyword">catch</span> (error) {
      alert(error.error_description || error.message);
    } <span class="hljs-keyword">finally</span> {
      setLoading(<span class="hljs-literal">false</span>);
    }
  };

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex mt-20 items-center justify-center"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex flex-col border p-4 rounded-lg shadow-lg w-64"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-2xl"</span>&gt;</span>Login.<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
        {loading() ? (
          "Sending magic link..."
        ) : (
          <span class="hljs-tag">&lt;&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
              <span class="hljs-attr">id</span>=<span class="hljs-string">"email"</span>
              <span class="hljs-attr">className</span>=<span class="hljs-string">"mt-2 border p-2 rounded-sm"</span>
              <span class="hljs-attr">type</span>=<span class="hljs-string">"email"</span>
              <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Your email"</span>
              <span class="hljs-attr">value</span>=<span class="hljs-string">{email()}</span>
              <span class="hljs-attr">onChange</span>=<span class="hljs-string">{(e)</span> =&gt;</span> setEmail(e.target.value)}
            &gt;<span class="hljs-tag">&lt;/<span class="hljs-name">input</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">Button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{handleLogin}</span>&gt;</span>Send Magic Link<span class="hljs-tag">&lt;/<span class="hljs-name">Button</span>&gt;</span>
          <span class="hljs-tag">&lt;/&gt;</span>
        )}
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    &lt;/div&gt;
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Login;
</code></pre>
<p>after creating our component we need to add the router to our <code>src/index.jsx</code></p>
<p><code>src/index.jsx</code> -</p>
<pre><code class="lang-javascript"><span class="hljs-comment">/* @refresh reload */</span>
<span class="hljs-keyword">import</span> { render } <span class="hljs-keyword">from</span> <span class="hljs-string">"solid-js/web"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"./index.css"</span>;
<span class="hljs-keyword">import</span> App <span class="hljs-keyword">from</span> <span class="hljs-string">"./App"</span>;
<span class="hljs-keyword">import</span> { Router } <span class="hljs-keyword">from</span> <span class="hljs-string">"@solidjs/router"</span>;

render(
  <span class="hljs-function">() =&gt;</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Router</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">App</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">Router</span>&gt;</span></span>
  ),
  <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"root"</span>)
);
</code></pre>
<p>Now, we need to add the <code>Routes</code> to our app entry point which is <code>src/App.jsx</code></p>
<p><code>src/App.jsx</code> -</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { createSignal, createEffect } <span class="hljs-keyword">from</span> <span class="hljs-string">"solid-js"</span>;
<span class="hljs-keyword">import</span> Login <span class="hljs-keyword">from</span> <span class="hljs-string">"./components/login"</span>;
<span class="hljs-keyword">import</span> Dashboard <span class="hljs-keyword">from</span> <span class="hljs-string">"./components/dashboard"</span>;
<span class="hljs-keyword">import</span> { supabase } <span class="hljs-keyword">from</span> <span class="hljs-string">"./supabaseClient"</span>;
<span class="hljs-keyword">import</span> Button <span class="hljs-keyword">from</span> <span class="hljs-string">"./components/button"</span>;
<span class="hljs-keyword">import</span> { Routes, Route, useNavigate } <span class="hljs-keyword">from</span> <span class="hljs-string">"@solidjs/router"</span>;
<span class="hljs-keyword">import</span> AddNotes <span class="hljs-keyword">from</span> <span class="hljs-string">"./components/AddNotes"</span>;
<span class="hljs-keyword">import</span> EditNotes <span class="hljs-keyword">from</span> <span class="hljs-string">"./components/EditNotes"</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">const</span> [session, setSession] = createSignal(<span class="hljs-literal">null</span>);
  <span class="hljs-keyword">const</span> navigate = useNavigate();

  createEffect(<span class="hljs-function">() =&gt;</span> {
    setSession(supabase.auth.session());
    supabase.auth.onAuthStateChange(<span class="hljs-function">(<span class="hljs-params">_event, session</span>) =&gt;</span> {
      setSession(session);
    });
  });

<span class="hljs-comment">// If we don't have a supabase session we log in.</span>
  createEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">if</span> (!supabase.auth.session()) {
      navigate(<span class="hljs-string">"/login"</span>);
    }
  });

  <span class="hljs-keyword">const</span> handleLogout = <span class="hljs-function">() =&gt;</span> {
    supabase.auth.signOut();
    navigate(<span class="hljs-string">"/login"</span>);
  };

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"container max-w-2xl mx-auto mt-10"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex items-center justify-between"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>solid-notes<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
        {session() &amp;&amp; <span class="hljs-tag">&lt;<span class="hljs-name">Button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{handleLogout}</span>&gt;</span>Logout<span class="hljs-tag">&lt;/<span class="hljs-name">Button</span>&gt;</span>}
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Routes</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">"/login"</span> <span class="hljs-attr">component</span>=<span class="hljs-string">{Login}</span> /&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">Routes</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>Now, let's start our app.</p>
<pre><code class="lang-javascript">yarn dev
</code></pre>
<p>we will have something like this on screen and we can log in to our app.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1660300694187/WVM8oYcX3.png" alt="Screenshot 2022-08-12 at 4.08.09 PM.png" /></p>
<h2 id="heading-crud">CRUD</h2>
<p>Now Let's Work on the core of our app.</p>
<p>we will start by creating notes</p>
<h4 id="heading-create-notes">Create Notes</h4>
<p>To, Create Notes we need to first create a table in our supabase database so that we can push our data to that table.</p>
<ul>
<li><p>Go to your app dashboard in supabase <code>https://app.supabase.com/</code></p>
</li>
<li><p>Go to the table editor and click on <code>New Table</code></p>
</li>
<li><p>After that give it a name we are going to name it <code>notes</code> in this tutorial but you can name it anything you like.</p>
</li>
<li><p>Add two columns - <code>Title</code> &amp; <code>Description</code> - with Text Type.</p>
</li>
</ul>
<p>Now, that we have our table setup, let's start adding some data to it.</p>
<p>Let's add all the route for all the component which we need we will add them as we go along in this tutorial.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Add All The Routes</span>
  &lt;Routes&gt;
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">"/login"</span> <span class="hljs-attr">component</span>=<span class="hljs-string">{Login}</span> /&gt;</span></span>
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">"/add"</span> <span class="hljs-attr">component</span>=<span class="hljs-string">{AddNotes}</span> /&gt;</span></span>
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">"/edit"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">"/:id"</span> <span class="hljs-attr">component</span>=<span class="hljs-string">{EditNotes}</span> /&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">Route</span>&gt;</span></span>
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">"/"</span> <span class="hljs-attr">component</span>=<span class="hljs-string">{Dashboard}</span> /&gt;</span></span>
 &lt;/Routes&gt;
</code></pre>
<p>Let's create <code>AddNotex.jsx</code> component which will help us in adding notes.</p>
<p><code>src/AddNotes.jsx</code> -</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { createSignal } <span class="hljs-keyword">from</span> <span class="hljs-string">"solid-js"</span>;
<span class="hljs-keyword">import</span> { supabase } <span class="hljs-keyword">from</span> <span class="hljs-string">"../supabaseClient"</span>;
<span class="hljs-keyword">import</span> Button <span class="hljs-keyword">from</span> <span class="hljs-string">"./button"</span>;
<span class="hljs-keyword">import</span> { useNavigate } <span class="hljs-keyword">from</span> <span class="hljs-string">"@solidjs/router"</span>;

<span class="hljs-keyword">const</span> AddNotes = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> navigate = useNavigate();
  <span class="hljs-keyword">const</span> [title, setTitle] = createSignal(<span class="hljs-string">""</span>);
  <span class="hljs-keyword">const</span> [description, setDescription] = createSignal(<span class="hljs-string">""</span>);

  <span class="hljs-keyword">const</span> handleSave = <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">if</span> (title().length &gt; <span class="hljs-number">0</span> &amp;&amp; description().length &gt; <span class="hljs-number">0</span>) {
      <span class="hljs-keyword">try</span> {
        <span class="hljs-keyword">await</span> supabase
          .from(<span class="hljs-string">"notes"</span>)
          .insert({ <span class="hljs-attr">title</span>: title(), <span class="hljs-attr">description</span>: description() });
      } <span class="hljs-keyword">catch</span> (error) {
        <span class="hljs-built_in">console</span>.error(error.message);
      }<span class="hljs-keyword">finally</span>{
        navigate(<span class="hljs-string">"/"</span>)
      }
    }
  };

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"max-w-2xl flex items-center"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex flex-col w-full"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-2xl mt-5"</span>&gt;</span>Create Note<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
          <span class="hljs-attr">value</span>=<span class="hljs-string">{title()}</span>
          <span class="hljs-attr">onChange</span>=<span class="hljs-string">{(e)</span> =&gt;</span> setTitle(e.target.value)}
          type="text"
          placeholder="Enter Title"
          className="border w-full rounded-md p-4 mt-2"
        /&gt;
        <span class="hljs-tag">&lt;<span class="hljs-name">textarea</span>
          <span class="hljs-attr">value</span>=<span class="hljs-string">{description()}</span>
          <span class="hljs-attr">onChange</span>=<span class="hljs-string">{(e)</span> =&gt;</span> setDescription(e.target.value)}
          className="mt-2 border rounded-md p-4"
          rows="5"
          placeholder="Notes Description"
        &gt;<span class="hljs-tag">&lt;/<span class="hljs-name">textarea</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{handleSave}</span> <span class="hljs-attr">classes</span>=<span class="hljs-string">"py-5"</span>&gt;</span>
          Save
        <span class="hljs-tag">&lt;/<span class="hljs-name">Button</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> AddNotes;
</code></pre>
<p>Preview-</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1660304359399/1y_FdzlAJ.png" alt="Screenshot 2022-08-12 at 5.09.15 PM.png" /></p>
<p>this component will allow us to add <code>Notes</code> to our app.</p>
<h4 id="heading-read-notes">Read Notes</h4>
<p>After Creating Some notes let's display those on our main route <code>/</code>.</p>
<p>Let's add the route for the dashboard and render all the notes for the preview.</p>
<p><code>components/dashboard.jsx</code> -</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> Button <span class="hljs-keyword">from</span> <span class="hljs-string">"./button"</span>;
<span class="hljs-keyword">import</span> Cards <span class="hljs-keyword">from</span> <span class="hljs-string">"./cards"</span>;
<span class="hljs-keyword">import</span> { useNavigate } <span class="hljs-keyword">from</span> <span class="hljs-string">"@solidjs/router"</span>;
<span class="hljs-keyword">import</span> { createEffect, createSignal } <span class="hljs-keyword">from</span> <span class="hljs-string">"solid-js"</span>;
<span class="hljs-keyword">import</span> { supabase } <span class="hljs-keyword">from</span> <span class="hljs-string">"../supabaseClient"</span>;

<span class="hljs-keyword">const</span> dashboard = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> navigate = useNavigate();
  <span class="hljs-keyword">const</span> [notes, setNotes] = createSignal([]);

  <span class="hljs-keyword">const</span> fetchNotes = <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">const</span> { data, error } = <span class="hljs-keyword">await</span> supabase.from(<span class="hljs-string">"notes"</span>).select(<span class="hljs-string">"*"</span>);
      <span class="hljs-keyword">if</span> (data) {
        setNotes(data);
      }
      <span class="hljs-keyword">if</span> (error) {
        <span class="hljs-built_in">console</span>.error(error.message);
      }
    } <span class="hljs-keyword">catch</span> (error) {
      <span class="hljs-built_in">console</span>.error(error.message);
    }
  };

  createEffect(<span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">await</span> fetchNotes();
  }, []);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"mt-10 flex items-center justify-center"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"w-full"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex items-center justify-between"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-2xl"</span>&gt;</span>All Notes<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> navigate("/add")} classes="bg-blue-500"&gt;
            Add Note
          <span class="hljs-tag">&lt;/<span class="hljs-name">Button</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        {notes().length
          ? notes().map(({ id, title, description }) =&gt; (
              <span class="hljs-tag">&lt;<span class="hljs-name">Cards</span>
                <span class="hljs-attr">key</span>=<span class="hljs-string">{id}</span>
                <span class="hljs-attr">id</span>=<span class="hljs-string">{id}</span>
                <span class="hljs-attr">title</span>=<span class="hljs-string">{title}</span>
                <span class="hljs-attr">description</span>=<span class="hljs-string">{description}</span>
                <span class="hljs-attr">reload</span>=<span class="hljs-string">{fetchNotes}</span>
              /&gt;</span>
            ))
          : "Add a note to get started"}
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> dashboard;
</code></pre>
<p><code>components/Cards.jsx</code> -</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> Button <span class="hljs-keyword">from</span> <span class="hljs-string">"./button"</span>;
<span class="hljs-keyword">import</span> { useNavigate } <span class="hljs-keyword">from</span> <span class="hljs-string">"@solidjs/router"</span>;
<span class="hljs-keyword">import</span> { supabase } <span class="hljs-keyword">from</span> <span class="hljs-string">"../supabaseClient"</span>;

<span class="hljs-keyword">const</span> Cards = <span class="hljs-function">(<span class="hljs-params">{ title, description, id, reload }</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> navigate = useNavigate();

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"w-full border p-2 mt-5 rounded-md"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-2xl"</span>&gt;</span>{title}<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"opacity-50"</span>&gt;</span>{description}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> navigate(`/edit/${id}`)}&gt;Edit<span class="hljs-tag">&lt;/<span class="hljs-name">Button</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{handleDelete}</span> <span class="hljs-attr">classes</span>=<span class="hljs-string">"bg-red-500 ml-2"</span>&gt;</span>
        Delete
      <span class="hljs-tag">&lt;/<span class="hljs-name">Button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Cards;
</code></pre>
<p>Preview -</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1660309891635/_kTGYYb9Y.png" alt="Screenshot 2022-08-12 at 6.41.26 PM.png" /></p>
<h4 id="heading-update-notes">Update Notes</h4>
<p>Now, Let's need to add the edit route component (<code>/edit</code>) which helps us in editing the notes.</p>
<p><code>EditNotes.jsx</code> -</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { createEffect, createSignal } <span class="hljs-keyword">from</span> <span class="hljs-string">"solid-js"</span>;
<span class="hljs-keyword">import</span> { supabase } <span class="hljs-keyword">from</span> <span class="hljs-string">"../supabaseClient"</span>;
<span class="hljs-keyword">import</span> Button <span class="hljs-keyword">from</span> <span class="hljs-string">"./button"</span>;
<span class="hljs-keyword">import</span> { useNavigate, useParams } <span class="hljs-keyword">from</span> <span class="hljs-string">"@solidjs/router"</span>;

<span class="hljs-keyword">const</span> EditNotes = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> navigate = useNavigate();
  <span class="hljs-keyword">const</span> [title, setTitle] = createSignal(<span class="hljs-string">""</span>);
  <span class="hljs-keyword">const</span> [description, setDescription] = createSignal(<span class="hljs-string">""</span>);
  <span class="hljs-keyword">const</span> params = useParams();

  createEffect(<span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">const</span> { data, error } = <span class="hljs-keyword">await</span> supabase
        .from(<span class="hljs-string">"notes"</span>)
        .select(<span class="hljs-string">"title, description"</span>)
        .match({ <span class="hljs-attr">id</span>: params.id });

      setTitle(data[<span class="hljs-number">0</span>].title);
      setDescription(data[<span class="hljs-number">0</span>].description);
      <span class="hljs-keyword">if</span> (error) {
        <span class="hljs-built_in">console</span>.error(error.message);
      }
    } <span class="hljs-keyword">catch</span> (error) {
      <span class="hljs-built_in">console</span>.error(error.message);
    }
  }, []);

  <span class="hljs-keyword">const</span> handleEdit = <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">if</span> (title().length &gt; <span class="hljs-number">0</span> &amp;&amp; description().length &gt; <span class="hljs-number">0</span>) {
      <span class="hljs-keyword">try</span> {
        <span class="hljs-keyword">await</span> supabase
          .from(<span class="hljs-string">"notes"</span>)
          .update({ <span class="hljs-attr">title</span>: title(), <span class="hljs-attr">description</span>: description() })
          .match({ <span class="hljs-attr">id</span>: params.id });
      } <span class="hljs-keyword">catch</span> (error) {
        <span class="hljs-built_in">console</span>.error(error.message);
      } <span class="hljs-keyword">finally</span> {
        navigate(<span class="hljs-string">"/"</span>);
      }
    }
  };

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">" max-w-2xl flex items-center"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex flex-col w-full"</span>&gt;</span>
        {title ? (
          <span class="hljs-tag">&lt;&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-2xl mt-5"</span>&gt;</span>Edit Note<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
              <span class="hljs-attr">value</span>=<span class="hljs-string">{title()}</span>
              <span class="hljs-attr">onChange</span>=<span class="hljs-string">{(e)</span> =&gt;</span> setTitle(e.target.value)}
              type="text"
              placeholder="Update Title"
              className="border w-full rounded-md p-4 mt-2"
            /&gt;
            <span class="hljs-tag">&lt;<span class="hljs-name">textarea</span>
              <span class="hljs-attr">value</span>=<span class="hljs-string">{description()}</span>
              <span class="hljs-attr">onChange</span>=<span class="hljs-string">{(e)</span> =&gt;</span> setDescription(e.target.value)}
              className="mt-2 border rounded-md p-4"
              rows="5"
              placeholder="Update Description"
            &gt;<span class="hljs-tag">&lt;/<span class="hljs-name">textarea</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">Button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{handleEdit}</span> <span class="hljs-attr">classes</span>=<span class="hljs-string">"py-5"</span>&gt;</span>
              Update
            <span class="hljs-tag">&lt;/<span class="hljs-name">Button</span>&gt;</span>
          <span class="hljs-tag">&lt;/&gt;</span>
        ) : (
          "Loading..."
        )}
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    &lt;/div&gt;
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> EditNotes;
</code></pre>
<p>This component Will allow us to handle the editing part of our app.</p>
<h4 id="heading-delete-notes">Delete Notes</h4>
<p>At last, we are going to handle deleting our notes.<br />for that, we will go to our <code>cards.jsx</code> component and add a new function called <code>handleDelete</code> which will delete the notes and fetch all the notes again.</p>
<p><code>cards.jsx</code> -</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> Button <span class="hljs-keyword">from</span> <span class="hljs-string">"./button"</span>;
<span class="hljs-keyword">import</span> { useNavigate } <span class="hljs-keyword">from</span> <span class="hljs-string">"@solidjs/router"</span>;
<span class="hljs-keyword">import</span> { supabase } <span class="hljs-keyword">from</span> <span class="hljs-string">"../supabaseClient"</span>;

<span class="hljs-keyword">const</span> Cards = <span class="hljs-function">(<span class="hljs-params">{ title, description, id, reload }</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> navigate = useNavigate();
  <span class="hljs-keyword">const</span> handleDelete = <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">const</span> { data, error } = <span class="hljs-keyword">await</span> supabase
        .from(<span class="hljs-string">"notes"</span>)
        .delete()
        .match({ <span class="hljs-attr">id</span>: id });
      <span class="hljs-keyword">if</span> (data) {
        reload();
      }
    } <span class="hljs-keyword">catch</span> (error) {
      <span class="hljs-built_in">console</span>.error(error.message);
    }
  };
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"w-full border p-2 mt-5 rounded-md"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-2xl"</span>&gt;</span>{title}<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"opacity-50"</span>&gt;</span>{description}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> navigate(`/edit/${id}`)}&gt;Edit<span class="hljs-tag">&lt;/<span class="hljs-name">Button</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{handleDelete}</span> <span class="hljs-attr">classes</span>=<span class="hljs-string">"bg-red-500 ml-2"</span>&gt;</span>
        Delete
      <span class="hljs-tag">&lt;/<span class="hljs-name">Button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Cards;
</code></pre>
<h2 id="heading-conclusion">Conclusion</h2>
<p>That's all I have for you! Hopefully, you learned something new.</p>
<p>Enjoy the rest of your day 👋</p>
]]></content:encoded></item><item><title><![CDATA[How to create Awesome text animation with framer-motion]]></title><description><![CDATA[Here is the video for this tutorial -
%[https://youtu.be/wgXLE_GZ9sM]
Hey Internet, In this blog, we will create text animations with framer-motion.
In this blog, we are going to use Next.js but you can follow this for any React Project.
So to get st...]]></description><link>https://blog.chetanverma.com/how-to-create-awesome-text-animation-with-framer-motion</link><guid isPermaLink="true">https://blog.chetanverma.com/how-to-create-awesome-text-animation-with-framer-motion</guid><category><![CDATA[animation]]></category><category><![CDATA[css animations]]></category><category><![CDATA[React]]></category><category><![CDATA[Next.js]]></category><category><![CDATA[framer-motion]]></category><dc:creator><![CDATA[Chetan verma]]></dc:creator><pubDate>Mon, 01 Aug 2022 12:16:58 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1659356232858/xR7AcHBUh.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-here-is-the-video-for-this-tutorial">Here is the video for this tutorial -</h2>
<p>%[https://youtu.be/wgXLE_GZ9sM]</p>
<p>Hey Internet, In this blog, we will create text animations with <a target="_blank" href="https://www.framer.com/motion/">framer-motion</a>.</p>
<p>In this blog, we are going to use Next.js but you can follow this for any React Project.</p>
<p>So to get started with that we need to first set up a <a target="_blank" href="https://nextjs.org/">Next.js</a> app with <a target="_blank" href="https://tailwindcss.com/">tailwindcss</a> and <a target="_blank" href="https://www.framer.com/motion/">framer-motion</a>.</p>
<p>in your terminal run these commands -</p>
<pre><code class="lang-javascript">npx create-next-app my-project
cd my-project
</code></pre>
<p>once that is complete we are going to add tailwindcss and framer-motion</p>
<p>for tailwind CSS follow this guide to set it up - https://tailwindcss.com/docs/guides/nextjs and for the framer-motion, we are going to run this command</p>
<pre><code class="lang-javascript">npm i framer-motion
</code></pre>
<p>so once we are done and set up let's get started and animate the text.</p>
<h2 id="heading-animating-text-by-word">Animating Text By Word</h2>
<p>We are going to create a new component under <code>component/AnimatedTextWord.js</code></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">const</span> AnimatedTextWord = <span class="hljs-function">(<span class="hljs-params">{ text }</span>) =&gt;</span> {
<span class="hljs-comment">// This will split the text into an array of word </span>
<span class="hljs-keyword">const</span> words = text.split(<span class="hljs-string">" "</span>);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      {words.map((word, index) =&gt; (
        <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{index}</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">marginRight:</span> "<span class="hljs-attr">5px</span>" }}&gt;</span>
          {word}
        <span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
      ))}
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> AnimatedTextWord;
</code></pre>
<h2 id="heading-centering-everything-on-the-screen">Centering Everything on the screen</h2>
<p>After creating the barebone of the component let's add it to our <code>index.js</code> page.</p>
<p><code>pages/index.js</code></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> AnimatedTextCharacter <span class="hljs-keyword">from</span> <span class="hljs-string">"../component/AnimatedTextCharacter"</span>;
<span class="hljs-keyword">import</span> AnimatedTextWord <span class="hljs-keyword">from</span> <span class="hljs-string">"../component/AnimatedTextWord"</span>;

<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">Home</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"container h-screen mx-auto flex flex-col items-center justify-center"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">AnimatedTextWord</span> <span class="hljs-attr">text</span>=<span class="hljs-string">"animated text with framer-motion"</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>We will have something like this on the screen -</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1659351934406/Pm0o3wyvS.png" alt="Screenshot 2022-08-01 at 4.35.28 PM.png" /></p>
<p>So let's get started on animating the text.</p>
<p>The next thing we have to do is to add motion to our text elements</p>
<p>we are going to use variants from <code>framer-motion</code> to have the two-state - <code>visible</code> &amp; <code>hidden</code></p>
<p><code>hidden</code> - Initial state of the elements</p>
<p><code>visible</code> - final state of the elements</p>
<p>then, <code>framer-motion</code> is going to do its magic to create animation between those states.</p>
<p>Here is the code -</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> { motion } <span class="hljs-keyword">from</span> <span class="hljs-string">"framer-motion"</span>;

<span class="hljs-keyword">const</span> AnimatedTextWord = <span class="hljs-function">(<span class="hljs-params">{ text }</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> words = text.split(<span class="hljs-string">" "</span>);

<span class="hljs-comment">// Variants for Container of words.</span>
  <span class="hljs-keyword">const</span> container = {
    <span class="hljs-attr">hidden</span>: { <span class="hljs-attr">opacity</span>: <span class="hljs-number">0</span> },
    <span class="hljs-attr">visible</span>: <span class="hljs-function">(<span class="hljs-params">i = <span class="hljs-number">1</span></span>) =&gt;</span> ({
      <span class="hljs-attr">opacity</span>: <span class="hljs-number">1</span>,
      <span class="hljs-attr">transition</span>: { <span class="hljs-attr">staggerChildren</span>: <span class="hljs-number">0.12</span>, <span class="hljs-attr">delayChildren</span>: <span class="hljs-number">0.04</span> * i },
    }),
  };

<span class="hljs-comment">// Variants for each word.</span>

  <span class="hljs-keyword">const</span> child = {
    <span class="hljs-attr">visible</span>: {
      <span class="hljs-attr">opacity</span>: <span class="hljs-number">1</span>,
      <span class="hljs-attr">x</span>: <span class="hljs-number">0</span>,
      <span class="hljs-attr">transition</span>: {
        <span class="hljs-attr">type</span>: <span class="hljs-string">"spring"</span>,
        <span class="hljs-attr">damping</span>: <span class="hljs-number">12</span>,
        <span class="hljs-attr">stiffness</span>: <span class="hljs-number">100</span>,
      },
    },
    <span class="hljs-attr">hidden</span>: {
      <span class="hljs-attr">opacity</span>: <span class="hljs-number">0</span>,
      <span class="hljs-attr">x</span>: <span class="hljs-number">20</span>,
      <span class="hljs-attr">transition</span>: {
        <span class="hljs-attr">type</span>: <span class="hljs-string">"spring"</span>,
        <span class="hljs-attr">damping</span>: <span class="hljs-number">12</span>,
        <span class="hljs-attr">stiffness</span>: <span class="hljs-number">100</span>,
      },
    },
  };

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">motion.div</span>
      <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">overflow:</span> "<span class="hljs-attr">hidden</span>", <span class="hljs-attr">display:</span> "<span class="hljs-attr">flex</span>", <span class="hljs-attr">fontSize:</span> "<span class="hljs-attr">2rem</span>" }}
      <span class="hljs-attr">variants</span>=<span class="hljs-string">{container}</span>
      <span class="hljs-attr">initial</span>=<span class="hljs-string">"hidden"</span>
      <span class="hljs-attr">animate</span>=<span class="hljs-string">"visible"</span>
    &gt;</span>
      {words.map((word, index) =&gt; (
        <span class="hljs-tag">&lt;<span class="hljs-name">motion.span</span>
          <span class="hljs-attr">variants</span>=<span class="hljs-string">{child}</span>
          <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">marginRight:</span> "<span class="hljs-attr">5px</span>" }}
          <span class="hljs-attr">key</span>=<span class="hljs-string">{index}</span>
        &gt;</span>
          {word}
        <span class="hljs-tag">&lt;/<span class="hljs-name">motion.span</span>&gt;</span>
      ))}
    <span class="hljs-tag">&lt;/<span class="hljs-name">motion.div</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> AnimatedTextWord;
</code></pre>
<p>after adding the motion to our elements we will have something like this -</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1659353226553/mM_djvM0r.gif" alt="Screen Recording 2022-08-01 at 4.54.23 PM.gif" /></p>
<p>Now we have our animating text word by word.</p>
<p>Let's quickly add the animation for <code>letters</code>.</p>
<p>we are going to do the same thing but now we are going to split the text into letters instead of words and remove some styling that we added in the word animation to add an extra <code>margin</code> to the left of each word.</p>
<p><code>components/AnimatedTextCharacter.js</code> -</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> { motion } <span class="hljs-keyword">from</span> <span class="hljs-string">"framer-motion"</span>;

<span class="hljs-keyword">const</span> AnimatedTextCharacter = <span class="hljs-function">(<span class="hljs-params">{ text }</span>) =&gt;</span> {
<span class="hljs-comment">// splitting text into letters</span>
  <span class="hljs-keyword">const</span> letters = <span class="hljs-built_in">Array</span>.from(text);

<span class="hljs-comment">// Variants for Container</span>
  <span class="hljs-keyword">const</span> container = {
    <span class="hljs-attr">hidden</span>: { <span class="hljs-attr">opacity</span>: <span class="hljs-number">0</span> },
    <span class="hljs-attr">visible</span>: <span class="hljs-function">(<span class="hljs-params">i = <span class="hljs-number">1</span></span>) =&gt;</span> ({
      <span class="hljs-attr">opacity</span>: <span class="hljs-number">1</span>,
      <span class="hljs-attr">transition</span>: { <span class="hljs-attr">staggerChildren</span>: <span class="hljs-number">0.03</span>, <span class="hljs-attr">delayChildren</span>: <span class="hljs-number">0.04</span> * i },
    }),
  };

<span class="hljs-comment">// Variants for each letter</span>
  <span class="hljs-keyword">const</span> child = {
    <span class="hljs-attr">visible</span>: {
      <span class="hljs-attr">opacity</span>: <span class="hljs-number">1</span>,
      <span class="hljs-attr">x</span>: <span class="hljs-number">0</span>,
      <span class="hljs-attr">y</span>: <span class="hljs-number">0</span>,
      <span class="hljs-attr">transition</span>: {
        <span class="hljs-attr">type</span>: <span class="hljs-string">"spring"</span>,
        <span class="hljs-attr">damping</span>: <span class="hljs-number">12</span>,
        <span class="hljs-attr">stiffness</span>: <span class="hljs-number">100</span>,
      },
    },
    <span class="hljs-attr">hidden</span>: {
      <span class="hljs-attr">opacity</span>: <span class="hljs-number">0</span>,
      <span class="hljs-attr">x</span>: <span class="hljs-number">-20</span>,
      <span class="hljs-attr">y</span>: <span class="hljs-number">10</span>,
      <span class="hljs-attr">transition</span>: {
        <span class="hljs-attr">type</span>: <span class="hljs-string">"spring"</span>,
        <span class="hljs-attr">damping</span>: <span class="hljs-number">12</span>,
        <span class="hljs-attr">stiffness</span>: <span class="hljs-number">100</span>,
      },
    },
  };

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">motion.div</span>
      <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">overflow:</span> "<span class="hljs-attr">hidden</span>", <span class="hljs-attr">display:</span> "<span class="hljs-attr">flex</span>", <span class="hljs-attr">fontSize:</span> "<span class="hljs-attr">2rem</span>" }}
      <span class="hljs-attr">variants</span>=<span class="hljs-string">{container}</span>
      <span class="hljs-attr">initial</span>=<span class="hljs-string">"hidden"</span>
      <span class="hljs-attr">animate</span>=<span class="hljs-string">"visible"</span>
    &gt;</span>
      {letters.map((letter, index) =&gt; (
        <span class="hljs-tag">&lt;<span class="hljs-name">motion.span</span> <span class="hljs-attr">variants</span>=<span class="hljs-string">{child}</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{index}</span>&gt;</span>
          {letter === " " ? "\u00A0" : letter}
        <span class="hljs-tag">&lt;/<span class="hljs-name">motion.span</span>&gt;</span>
      ))}
    <span class="hljs-tag">&lt;/<span class="hljs-name">motion.div</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> AnimatedTextCharacter;
</code></pre>
<p>Now at last we just need to add <code>AnimatedTextCharacter</code> To our <code>index.js</code> page.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> AnimatedTextCharacter <span class="hljs-keyword">from</span> <span class="hljs-string">"../component/AnimatedTextCharacter"</span>;
<span class="hljs-keyword">import</span> AnimatedTextWord <span class="hljs-keyword">from</span> <span class="hljs-string">"../component/AnimatedTextWord"</span>;

<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">Home</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"container h-screen mx-auto flex flex-col items-center justify-center"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">AnimatedTextWord</span> <span class="hljs-attr">text</span>=<span class="hljs-string">"animated text with framer-motion"</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">AnimatedTextCharacter</span> <span class="hljs-attr">text</span>=<span class="hljs-string">"animated text with framer-motion"</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>Now, we will have both animations -</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1659353973923/ioJWowHFp.gif" alt="Screen Recording 2022-08-01 at 5.08.51 PM.gif" /></p>
<hr />
<h2 id="heading-conclusion">Conclusion</h2>
<p>That's all I have for you! Hopefully, you learned something new, and you use later end up using this animation to liven up your own websites!</p>
<p>Enjoy the rest of your day 👋</p>
<hr />
<p>If you enjoyed this article, give it a ❤️ so others can find it too.</p>
<p>For more such content, stay in touch on <a target="_blank" href="https://twitter.com/realchetanverma">Twitter</a></p>
<p>Contact Me:</p>
<p><a target="_blank" href="https://chetanverma.com/">Portfolio</a> | <a target="_blank" href="https://github.com/chetanverma16">Github</a> | <a target="_blank" href="https://www.linkedin.com/in/chetanverma7/">LinkedIn</a> | <a target="_blank" href="https://twitter.com/realchetanverma">Twitter</a></p>
]]></content:encoded></item><item><title><![CDATA[React Portfolio Template v3.0]]></title><description><![CDATA[https://www.youtube.com/watch?v=62_HLbx2zLQ&t=9s
Hi everyone,
I am very excited to share a new release for my open source project react-portfolio-template (v3.0)
Project - https://github.com/chetanverma16/react-portfolio-template
Release Notes - http...]]></description><link>https://blog.chetanverma.com/react-portfolio-template-v30</link><guid isPermaLink="true">https://blog.chetanverma.com/react-portfolio-template-v30</guid><category><![CDATA[React]]></category><category><![CDATA[portfolio]]></category><category><![CDATA[Beginner Developers]]></category><category><![CDATA[beginner]]></category><dc:creator><![CDATA[Chetan verma]]></dc:creator><pubDate>Mon, 25 Jul 2022 14:28:10 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1658759110690/LWkT8lm3K.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.youtube.com/watch?v=62_HLbx2zLQ&amp;t=9s">https://www.youtube.com/watch?v=62_HLbx2zLQ&amp;t=9s</a></div>
<p>Hi everyone,
I am very excited to share a new release for my open source project react-portfolio-template (v3.0)</p>
<p>Project - https://github.com/chetanverma16/react-portfolio-template
Release Notes - https://github.com/chetanverma16/react-portfolio-template/releases/tag/3.0</p>
<p>Some of the new things added -</p>
<ul>
<li>Added GUI for editing the personal Data.</li>
<li>Blog CRUD GUI (Now create your blog fast and easy with the new UI)</li>
<li>Responsive improvements</li>
<li>New Mobile Menu</li>
<li>some bug fixes and performance improvements.</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[How to build a portfolio website using Next.js and TailwindCSS]]></title><description><![CDATA[Hey internet, in this blog, we are going to create a developer/designer portfolio using react-portfolio-template which is a portfolio template based on Next.js & TailwindCSS.
If you don't want to read this article you can watch a youtube video about ...]]></description><link>https://blog.chetanverma.com/how-to-build-a-portfolio-website-using-nextjs-and-tailwindcss</link><guid isPermaLink="true">https://blog.chetanverma.com/how-to-build-a-portfolio-website-using-nextjs-and-tailwindcss</guid><category><![CDATA[portfolio]]></category><category><![CDATA[free]]></category><category><![CDATA[GitHub]]></category><category><![CDATA[Open Source]]></category><category><![CDATA[Web Development]]></category><dc:creator><![CDATA[Chetan verma]]></dc:creator><pubDate>Tue, 19 Jul 2022 13:37:47 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1658237657300/qRQFaVtci.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Hey internet, in this blog, we are going to create a developer/designer portfolio using <a target="_blank" href="https://github.com/chetanverma16/react-portfolio-template">react-portfolio-template</a> which is a portfolio template based on Next.js &amp; TailwindCSS.</p>
<h4 id="heading-if-you-dont-want-to-read-this-article-you-can-watch-a-youtube-video-about-it">If you don't want to read this article you can watch a youtube video about it</h4>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.youtube.com/watch?v=8cmJ2kR4SpM">https://www.youtube.com/watch?v=8cmJ2kR4SpM</a></div>
<p> </p>
<p>so, let's get started</p>
<h3 id="heading-setting-up-locally">Setting Up Locally</h3>
<ul>
<li><p>To get started with the template, at first we need to get it up and running locally on our machine, so to do that you can clone this repo.<br />  <code>git clone https://github.com/chetanverma16/react-portfolio-template</code></p>
</li>
<li><p>once you have cloned this repo then we need to install some dependencies.<br />  <code>npm install</code></p>
</li>
<li><p>After installing the dependencies we can run the next.js server.<br />  <code>npm run dev</code></p>
</li>
</ul>
<p>after following these steps we will have something like this running on <code>localhost:3000</code> -</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1658184200895/gJZTkAowc.png" alt="Screenshot 2022-07-19 at 4.13.16 AM.png" /></p>
<p>now we are good to go with the next steps.</p>
<h3 id="heading-editing-some-data">Editing Some Data</h3>
<p>So, now we have something running on the screen let's edit the data and make this portfolio custom to our needs.</p>
<p>now, we just need to click on the button <code>Edit Data</code> which you can see on the bottom right corner of the home page or you can directly go to <code>localhost:3000/edit</code></p>
<p>you will see a GUI something like this -</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1658184417408/R3A2-sg1-.png" alt="Screenshot 2022-07-19 at 4.16.54 AM.png" /></p>
<p>Where you will see a bunch of fields that we can edit and there are multiple tabs for different sections such as -</p>
<ul>
<li><p>Header - this tab is for editing the header of the website</p>
</li>
<li><p>Project- edit the project section.</p>
</li>
<li><p>Services - edit the services section.</p>
</li>
<li><p>About - edit the about section.</p>
</li>
<li><p>Social - edit the socials or personal links.</p>
</li>
</ul>
<p>so, once you have edited the portfolio according to your needs you can now go and click on the <code>save</code> button.</p>
<p>and once this is saved you can go back to the home page (<code>localhost:3000</code>) you will be able to see all the changes you have made, and now we have our custom portfolio made in just 5 minutes.</p>
<h3 id="heading-editing-blog-data">Editing Blog Data</h3>
<p>you might have noticed there is a blog page on our portfolio that can be hidden through the <code>localhost:3000/edit</code> page, if you don't want to have a blog on your portfolio.</p>
<p>but if you do, you might want to know how to edit the blogs. so, let's do that you might be able to see three demo blogs on the portfolio. to edit those blogs we need to go to our code and go to the <code>_posts</code> folder. you will find the demo blogs written in <code>markdown</code> you can go into any of those blogs and start editing those.</p>
<p>to create a new blog, we just need to create a new markdown blog and add some markdown variables for adding the structure to the blog.</p>
<p>here are the variables that we need to add-</p>
<pre><code class="lang-javascript">---
date: <span class="hljs-string">'2022-06-10T18:30:00.000Z'</span>
<span class="hljs-attr">title</span>: Ok Let<span class="hljs-string">'s See How this blog will turn out
tagline: This is a Tagline If you want to add.
preview: &gt;-
  Lorem Ipsum is simply dummy text of the printing and typesetting industry.
  Lorem Ipsum has been the industry'</span>s standard dummy text ever since the <span class="hljs-number">1500</span>s,
  when an unknown printer took a galley <span class="hljs-keyword">of</span> type and scrambled it to make a type
  specimen book.
image: &gt;-
  https:<span class="hljs-comment">//images.unsplash.com/photo-1656188505561-19f1a1b6cda8?ixlib=rb-1.2.1&amp;ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&amp;auto=format&amp;fit=crop&amp;w=1632&amp;q=80</span>
keywords: <span class="hljs-string">"Keyword One, Keyword Two"</span>
<span class="hljs-attr">author</span>:
  authorname: Author One
  <span class="hljs-attr">authorimage</span>: &gt;-
    https:<span class="hljs-comment">//images.unsplash.com/photo-1599566150163-29194dcaad36?ixlib=rb-1.2.1&amp;ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&amp;auto=format&amp;fit=crop&amp;w=687&amp;q=80</span>
readingtime: <span class="hljs-number">3</span>
---
<span class="hljs-comment">// Content Goes Here</span>
</code></pre>
<p>so once you have added the variables and added the content for your blog you can save the file and try reloading <code>localhost:3000</code> you will be able to see your new blog under <code>localhost:3000/blog</code>.</p>
<h3 id="heading-deploying">Deploying</h3>
<p>Once we are done with our portfolio it's time to deploy. there are many ways to deploy this portfolio.</p>
<p>In this blog, we are going to do it through <code>Netlify</code></p>
<ul>
<li><p>the first thing you have to do is to go to <a target="_blank" href="https://www.netlify.com/">netlify.com</a> and log in or create an account.</p>
</li>
<li><p>once you are logged in you can create a new site by clicking on <code>add new site</code> and then import an existing project.</p>
</li>
<li><p>after that click the git provider you are using to import your portfolio template.</p>
</li>
<li><p>now select the repo you want to deploy</p>
</li>
<li><p>and click on deploy site.</p>
</li>
</ul>
<p>Netlify will do it's magic and will deploy your site 🚀.</p>
<p>Awesome now we have our portfolio up and running</p>
<hr />
<p>Portfolio Template - https://github.com/chetanverma16/react-portfolio-template</p>
<p>Thank you for reading this far.</p>
<p>If you enjoyed this article, give it a ❤️ so others can find it too.</p>
<p>For more frequent tips, stay in touch on <a target="_blank" href="https://twitter.com/realchetanverma">Twitter</a></p>
<p>Contact Me:</p>
<p><a target="_blank" href="http://chetanverma.com/">Portfolio</a> | <a target="_blank" href="https://github.com/chetanverma16">Github</a> | <a target="_blank" href="https://www.linkedin.com/in/chetanverma7/">LinkedIn</a> | <a target="_blank" href="https://twitter.com/realchetanverma">Twitter</a></p>
]]></content:encoded></item><item><title><![CDATA[How to become a web developer in 2022 (My Take)]]></title><description><![CDATA[This is my take on becoming a kick-ass web developer in 2022
Hey,
Internet people, I am chetan verma a full stack web developer primarily working on the web side of things.
I started out in 2014 and have been working on the internet ever since and in...]]></description><link>https://blog.chetanverma.com/how-to-become-a-web-developer-in-2022-my-take</link><guid isPermaLink="true">https://blog.chetanverma.com/how-to-become-a-web-developer-in-2022-my-take</guid><category><![CDATA[Developer]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[Web Design]]></category><category><![CDATA[Frontend Development]]></category><category><![CDATA[Beginner Developers]]></category><dc:creator><![CDATA[Chetan verma]]></dc:creator><pubDate>Thu, 07 Apr 2022 13:15:53 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1649336841198/RFiaa7mfx.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3 id="heading-this-is-my-take-on-becoming-a-kick-ass-web-developer-in-2022">This is my take on becoming a kick-ass web developer in 2022</h3>
<p>Hey,
Internet people, I am chetan verma a full stack web developer primarily working on the web side of things.</p>
<p>I started out in 2014 and have been working on the internet ever since and in this blog, I will take you around the internet to become one yourself.</p>
<blockquote>
<p>if you don't want to read this full article you can jump to the last for actionable steps and resources.</p>
</blockquote>
<p><strong>so let's get going</strong></p>
<p>so before getting into the details we need to understand the types of developers there are:</p>
<ul>
<li><p>Frontend Developer - These web developers focus on the user-facing sides of websites. They create intuitive user interfaces with a keen eye for compelling design.</p>
</li>
<li><p>Backend Developer - These web developers specialize in websites' nuts and bolts, optimizing the crucial hidden elements most users never see. They often design databases and use languages like PHP, CSS, or Python.</p>
</li>
<li><p>Fullstack Developer -These web developers combine front-end and back-end development. They consider the creation process from both angles and possess the skills to complete tasks on either end of the spectrum.</p>
</li>
</ul>
<p>now that is out of the way let's talk about the skills that are required for each type of developer.</p>
<p>There are some core skills which is required by each type of developer and there is some certain skill set that is specific to the type of developer and type of work you are trying to accomplish.</p>
<p>So Let's talk about the core skill set which is required by all types of web developers (OGs).</p>
<p>Those Are - </p>
<ul>
<li>HTML</li>
<li>CSS</li>
<li>JavaScript</li>
</ul>
<p>These are the only skillset required to spinoff a website that will work on the web and can get the job done pretty well.
All the other fancy stuff in the web developer space are derived from these core languages only so learning those will definitely make you an awesome web developer.</p>
<p>let's talk about these in detail.</p>
<ul>
<li>HTML &amp; CSS</li>
</ul>
<p>These languages are easy to grasp and are collectively called markup languages which are used to define the part of web structure and styling of those elements.</p>
<ul>
<li>JavaScript</li>
</ul>
<p>This is the language which I love the most. it is just amazing
it is a scripting language used to add dynamic nature to the web and gives all the superpower to the website or web app.</p>
<p>Now we are aware that where to start.</p>
<p>Once you are comfortable with those skills, now it is time to go in more depth and learn modern web development and chose the path to follow.</p>
<p>Now Let's talk about more focused stuff.</p>
<h3 id="heading-frontend-web-developer">Frontend Web Developer</h3>
<p>Now here comes the framework for writing and structuring your website or web apps.</p>
<p>Let's talk about the most used framework in the frontend world and my personal favorite which I use every day.</p>
<p>All of these frameworks do similar work but the way of achieving those results are different in each of the frameworks.</p>
<ul>
<li><p><a target="_blank" href="https://reactjs.org/">React</a> (❤️):
This is the most loved frontend framework developed by Facebook and used by gazillions of web apps. this is my personal favorite</p>
</li>
<li><p><a target="_blank" href="https://vuejs.org/">Vue</a>:
This framework started out as a side project by an awesome google developer Evan You. and now shares the leaderboard with other big frontend frameworks.</p>
</li>
<li><p><a target="_blank" href="https://angular.io/">Angular</a>:
This is the oldest and battle-tested framework by google to create awesome single-page applications.</p>
</li>
</ul>
<p>So now we know what are the best frontend frameworks.
you can choose any one of them to get started and become the full-fledged frontend web developer</p>
<blockquote>
<p>Actionable Step - Learn React / Vue / Angular</p>
</blockquote>
<h3 id="heading-backend-web-developer">Backend Web Developer</h3>
<p>So, if you want to become a backend web developer there are tons of things you can learn to become one you can choose your favorite programming language and each one of them has a framework to create an awesome backend for you.</p>
<p>Some of thems are - </p>
<ul>
<li><a target="_blank" href="https://rubyonrails.org/">Ruby On Rails</a></li>
<li><a target="_blank" href="https://www.djangoproject.com/">Django</a> / <a target="_blank" href="https://flask.palletsprojects.com/en/2.1.x/">Flask</a> (Python)</li>
<li><a target="_blank" href="https://go.dev/">Go</a></li>
<li><a target="_blank" href="https://www.rust-lang.org/">Rust</a></li>
<li><a target="_blank" href="https://expressjs.com/">Express.js</a> / <a target="_blank" href="https://koajs.com/">koa.js</a> (Node.js)</li>
</ul>
<p>and many more...
you can choose one of them and start learning those.
personally, I like <a target="_blank" href="https://expressjs.com/">Express.js</a> because it is based on javascript and we don't have to learn the syntax of a new language.</p>
<blockquote>
<p>Actionable Step - Learn any of the above backend frameworks</p>
</blockquote>
<h3 id="heading-full-stack-web-developer">Full Stack Web Developer</h3>
<p>Now For the full stack web developer, you have to combine the skill sets of both the frontend web developer and backend developer.</p>
<blockquote>
<p>Actionable Step - Learn any frontend framework and any backend framework</p>
</blockquote>
<h3 id="heading-some-other-important-stuff-to-learn">Some Other Important Stuff To Learn</h3>
<ul>
<li>CSS Preprocessors (<a target="_blank" href="https://lesscss.org/">LESS</a> &amp; <a target="_blank" href="https://sass-lang.com/">SASS</a>)</li>
</ul>
<p>These Are CSS Transpilers and make it very easy to write CSS.CSS Transpilers lets you do things that aren't normally supported, like nesting CSS rules and other awesome stuff.</p>
<ul>
<li>Design Patterns</li>
</ul>
<p>It is the way of writing your code that can be reusable and easy to debug.
Having a foundation in this will make you a far better developer in any programming language.</p>
<p>Resources - <a target="_blank" href="https://www.dofactory.com/javascript/design-patterns">Javascript Design Patterns</a>, <a target="_blank" href="https://www.patterns.dev/posts/classic-design-patterns/">Learning JavaScript Design Patterns</a>.</p>
<ul>
<li>Git (Version Control)</li>
</ul>
<p>This is by far the most important skill set that a web developer could possess.
git is a super powerful tool that can help you keep a track of the changes you make to your code and commit those changes.
if things go wrong you can revert back to those changes or commits.</p>
<p>Resources - https://www.atlassian.com/git/tutorials, https://learngitbranching.js.org/</p>
<p>Now, we are ready to get a job as web developers but there are certain things that we have to do on the web to get that job.</p>
<p>so let's start</p>
<h3 id="heading-get-a-portfolio">Get a Portfolio :</h3>
<p>you can get away without a portfolio but having one will make a huge difference in your job search it will get you more opportunities than you can imagine and if you have a blog as well then it is icing on the cake.</p>
<p>Create a portfolio with past projects which you have built while learning to code, if you don't have any you can create some projects for yourself and host those online.</p>
<p>Some Resources to get started with your portfolio - </p>
<p>there are a bunch of services that can help you create a portfolio over the web, you can do a google search to see which one you like.</p>
<p>I have a small portfolio template which based on react that you can use instantly to create your website.</p>
<p>here is the link - </p>
<ul>
<li>Github - https://github.com/chetanverma16/react-portfolio-template</li>
<li>Live - https://react-portfolio-template.netlify.app/</li>
</ul>
<p>Now that you have a portfolio let's go to the next step.</p>
<h3 id="heading-start-applying">Start Applying.</h3>
<p>Now it is time to start applying for the web developer role.</p>
<p>I am listing down some of the awesome job boards which I have used and are awesome to find your first job.</p>
<p>Job Boards - </p>
<ul>
<li><a target="_blank" href="https://angel.co/">Angel List</a></li>
<li><a target="_blank" href="www.workatastartup.com">workatastartup</a></li>
<li><a target="_blank" href="https://remotehunt.com/">Remote Hunt</a></li>
<li><a target="_blank" href="https://himalayas.app/">Himalyas App</a></li>
<li><a target="_blank" href="weworkremotely.com">WeWorkRemotely</a></li>
<li><a target="_blank" href="https://www.linkedin.com/jobs/">LinkedIn Jobs</a></li>
</ul>
<p>Thank you for reading out this article.</p>
<p>⚡</p>
<p>Here is a small summary of this article.</p>
<h3 id="heading-conclusion">Conclusion</h3>
<p>The job market is getting tougher. The more traditional jobs are phased out every day. So, why not learn a skill that will keep you employed (and possibly wealthy) for the foreseeable future?</p>
<p>That’s the big advantage of web development. The great part is- that you don’t need a fancy expensive degree to get into the field. Simply by following the steps we’ve listed out here, you can start out the path of becoming a web developer.</p>
<p>To recap, here are the basic steps to becoming a web developer:</p>
<ul>
<li>Learn the Basics of HTML, CSS, and Javascript</li>
<li>Frontend Developer - Learn <a target="_blank" href="https://reactjs.org/">React</a> / <a target="_blank" href="https://vuejs.org/">Vue</a> / <a target="_blank" href="https://angular.io/">Angular</a></li>
<li>Backend Developer - <ul>
<li><a target="_blank" href="https://rubyonrails.org/">Ruby On Rails</a></li>
<li><a target="_blank" href="https://www.djangoproject.com/">Django</a> / <a target="_blank" href="https://flask.palletsprojects.com/en/2.1.x/">Flask</a> (Python)</li>
<li><a target="_blank" href="https://go.dev/">Go</a></li>
<li><a target="_blank" href="https://www.rust-lang.org/">Rust</a></li>
<li><a target="_blank" href="https://expressjs.com/">Express.js</a> / <a target="_blank" href="https://koajs.com/">koa.js</a> (Node.js)</li>
</ul>
</li>
<li>Full Stack Web Developer - Do the actionable step of Frontend &amp; Backend Development.</li>
</ul>
<p>Now after getting ready with all those skill sets we have to get into the market
steps :</p>
<ul>
<li>Get a Portfolio </li>
<li>Get on Job Boards</li>
</ul>
<hr />
<h3 id="heading-all-resources">All Resources -</h3>
<ul>
<li><a target="_blank" href="https://www.freecodecamp.org/">Free Code Camp</a></li>
<li><a target="_blank" href="https://www.codecademy.com/">Codecademy</a></li>
<li>https://www.khanacademy.org/computing/computer-programming</li>
<li>https://www.w3schools.com/</li>
<li>https://www.theodinproject.com/</li>
<li>Design Patterns - <a target="_blank" href="https://www.dofactory.com/javascript/design-patterns">Javascript Design Patterns</a>, <a target="_blank" href="https://www.patterns.dev/posts/classic-design-patterns/">Learning JavaScript Design Patterns</a></li>
<li>Learn Git - https://www.atlassian.com/git/tutorials, https://learngitbranching.js.org/</li>
</ul>
<h3 id="heading-get-free-portfolio">Get Free Portfolio</h3>
<ul>
<li>Github - https://github.com/chetanverma16/react-portfolio-template</li>
<li>Live - https://react-portfolio-template.netlify.app/</li>
</ul>
<h3 id="heading-job-boards">Job Boards</h3>
<ul>
<li><a target="_blank" href="https://angel.co/">Angel List</a></li>
<li><a target="_blank" href="www.workatastartup.com">workatastartup</a></li>
<li><a target="_blank" href="https://remotehunt.com/">Remote Hunt</a></li>
<li><a target="_blank" href="https://himalayas.app/">Himalyas App</a></li>
<li><a target="_blank" href="weworkremotely.com">WeWorkRemotely</a></li>
<li><a target="_blank" href="https://www.linkedin.com/jobs/">LinkedIn Jobs</a></li>
</ul>
<p>Thank you for reading this far.</p>
<p>If you enjoyed this article, give it a ❤️ so others can find it too.</p>
<p>For more frequent tips, <a target="_blank" href="https://twitter.com/realchetanverma">stay in touch on Twitter</a></p>
<p>Contact Me:</p>
<p><a target="_blank" href="https://chetanverma.com/">Portfolio</a> | <a target="_blank" href="https://github.com/chetanverma16">Github</a> | <a target="_blank" href="https://www.linkedin.com/in/chetanverma7/">LinkedIn</a> | <a target="_blank" href="https://twitter.com/realchetanverma">Twitter</a></p>
]]></content:encoded></item></channel></rss>