Close Menu
    DevStackTipsDevStackTips
    • Home
    • News & Updates
      1. Tech & Work
      2. View All

      CodeSOD: A Unique Way to Primary Key

      July 22, 2025

      BrowserStack launches Figma plugin for detecting accessibility issues in design phase

      July 22, 2025

      Parasoft brings agentic AI to service virtualization in latest release

      July 22, 2025

      Node.js vs. Python for Backend: 7 Reasons C-Level Leaders Choose Node.js Talent

      July 21, 2025

      The best CRM software with email marketing in 2025: Expert tested and reviewed

      July 22, 2025

      This multi-port car charger can power 4 gadgets at once – and it’s surprisingly cheap

      July 22, 2025

      I’m a wearables editor and here are the 7 Pixel Watch 4 rumors I’m most curious about

      July 22, 2025

      8 ways I quickly leveled up my Linux skills – and you can too

      July 22, 2025
    • Development
      1. Algorithms & Data Structures
      2. Artificial Intelligence
      3. Back-End Development
      4. Databases
      5. Front-End Development
      6. Libraries & Frameworks
      7. Machine Learning
      8. Security
      9. Software Engineering
      10. Tools & IDEs
      11. Web Design
      12. Web Development
      13. Web Security
      14. Programming Languages
        • PHP
        • JavaScript
      Featured

      The Intersection of Agile and Accessibility – A Series on Designing for Everyone

      July 22, 2025
      Recent

      The Intersection of Agile and Accessibility – A Series on Designing for Everyone

      July 22, 2025

      Zero Trust & Cybersecurity Mesh: Your Org’s Survival Guide

      July 22, 2025

      Execute Ping Commands and Get Back Structured Data in PHP

      July 22, 2025
    • Operating Systems
      1. Windows
      2. Linux
      3. macOS
      Featured

      A Tomb Raider composer has been jailed — His legacy overshadowed by $75k+ in loan fraud

      July 22, 2025
      Recent

      A Tomb Raider composer has been jailed — His legacy overshadowed by $75k+ in loan fraud

      July 22, 2025

      “I don’t think I changed his mind” — NVIDIA CEO comments on H20 AI GPU sales resuming in China following a meeting with President Trump

      July 22, 2025

      Galaxy Z Fold 7 review: Six years later — Samsung finally cracks the foldable code

      July 22, 2025
    • Learning Resources
      • Books
      • Cheatsheets
      • Tutorials & Guides
    Home»Development»How to Build a Dynamic Wardrobe App with React Drag and Drop

    How to Build a Dynamic Wardrobe App with React Drag and Drop

    May 5, 2025

    Have you ever found yourself stuck deciding what color outfit to wear? Maybe you’re mixing and matching different tops and bottoms, unsure if the colors go together. It’s a common dilemma – so common that many of us turn to friends or family for a second opinion before stepping out for a meeting or a hangout.

    But what if you’re alone and need to make that choice quickly? Imagine having an app where you can drag and drop different clothing colors on your screen, instantly visualizing your outfit. If it looks good, that’s all the validation you need – no more second-guessing your look.

    In this tutorial, we’ll build a dynamic wardrobe app using React. You’ll learn to structure components, handle drag-and-drop interactions, and craft a smooth user experience. Let’s get straight into it!

    Here’s what we’ll cover:

    • Prerequisites

    • Steps to Create a Dynamic Wardrobe using React

      • Step 1: Setting Up Your Project

      • Step 2: Setting Up States

      • Step 3: Defining Color Options

      • Step 4: Implementing Drag and Drop Functionality

      • Step 5: Building the User Interface

      • Step 6: Putting It All Together

    • Conclusion

    Prerequisites

    Before we start coding, make sure you have:

    • Basic knowledge of React.

    • A code editor of your choice.

    Steps to Create a Dynamic Wardrobe using React

    We’re going to go through how to build this project step by step, so it’s easy to follow along. By the end, you’ll understand exactly how drag and drop functionality in React works.

    Step 1: Setting Up Your Project

    First and foremost, you need to set up React and Tailwind CSS using Vite in a project. If you don’t know how to do that, check out this article and follow the steps. When you’re done, come back here, and let’s continue building.

    If you already have a React project with Tailwind CSS you want to use, that’s great too.

    Step 2: Setting Up States

    We’ll start by setting up our states. If you have no idea what states are you can read my article on states here. In this simple project, we’ll have only two states: one for the selected top color (selectedTop) and the other for the selected bottom color (selectedBottom). We’ll be setting the initial value of both states to white (with hex code of #ffffff), as shown below:

    const [selectedTop, setSelectedTop] = useState("#ffffff");
    
    const [selectedBottom, setSelectedBottom] = useState("#ffffff");
    

    Step 3: Defining Color Options

    Next, we define an array of color options for the outfits:

    const colorOptions = [
    
    "#ff0000", // Red
    
    "#0000ff", // Blue
    
    "#ffff00", // Yellow
    
    "#00ff00", // Green
    
    "#ff00ff", // Pink
    
    "#808080", // Gray
    
    "#000000", // Black
    
    "#ffffff", // White
    
    ];
    

    The colorOptions array provides a vibrant palette of colors that users can drag onto clothing items.

    Step 4: Implementing Drag and Drop Functionality

    Now, let’s create the drag and drop functionality, which is the core aspect of this project. We’ll need event handler functions to handle certain events when they are triggered by specific user interaction or browser events – in this case, dragging and dropping.

    Here are the event handlers we need to implement the drag and drop functionality:

    1. handleDragStart

    This function is triggered when the user starts dragging a color block from the color palette (typically triggered via onDragStart in JSX).

    const handleDragStart = (e, color) => {
    
    e.dataTransfer.setData("color", color);
    
    };
    

    Breaking it down:

    • const handleDragStart = (e, color) => { ... }: This function accepts two parameters – the drag event object (e) and color, a custom value representing the color associated with the color block being dragged.

    • e.dataTransfer.setData("color", color):

      • dataTransfer is a property of the drag event that holds data being dragged.

      • .setData("color", color) stores the value of color under the key “color”.

    1. handleDropOnTop

    This function is triggered when the color block is dropped onto the “top” section of your outfit interface.

    const handleDropOnTop = (e) => {
    
    e.preventDefault();
    
    const color = e.dataTransfer.getData("color");
    
    setSelectedTop(color);
    
    };
    

    Breaking it down:

    • const handleDropOnTop = (e) => { … }: This function takes a single argument e, which is the event object representing the drop action.

    • e.preventDefault(): By default, the browser won’t allow dropping an item unless you explicitly prevent the default behavior. This ensures the drop target can accept the dragged item.

    • const color = e.daaTransfer.getData(“color”): retrieves the data previously set during the drag operation using setData(“color”, color) in handleDragStart .

    • setSelectedTop(color): The color data will be used to update the selectedTop state that tracks the currently selected top clothing color. This will typically cause the UI to re-render, showing the dropped color on the “top” section of the outfit.

    1. handleDropOnBottom

    This function is triggered when the color block is dropped onto the “bottom” section of your outfit interface.

    const handleDropOnBottom = (e) => {
    
    e.preventDefault();
    
    const color = e.dataTransfer.getData("color");
    
    setSelectedBottom(color);
    
    };
    

    Breaking it down:

    • const handleDropOnBottom = (e) => { ... }: This function takes a single argument e, which is the event object representing the drop action.

    • e.preventDefault(): By default, the browser won’t allow dropping an item unless you explicitly prevent the default behavior. This ensures the drop target can accept the dragged item.

    • const color = e.dataTransfer.getData("color"): Retrieves the data previously set during the drag operation using setData("color", color) in handleDragStart.

    • setSelectedBottom(color): The color data will be used to update the selectedBottom state that tracks the currently selected top clothing color. This will typically cause the UI to re-render, showing the dropped color on the “bottom” section of the outfit.

    1. allowDrop

    This event handler function enables a drop target by preventing the browser’s default behavior, which otherwise disallows dropping elements.

    const allowDrop = (e) => {
    
    e.preventDefault();
    
    };
    

    Step 5: Building the User Interface

    Having finished the functional part of our wardrobe project, we want to build out the visual part that users can see and interact with.

    The UI will consist of two parts: a color palette on the left and an outfit preview on the right. The color palette section will include 30 color blocks while the outfit preview section will include a top and bottom, onto which selected colors can be dragged and applied to see how they look together.

    This is a visual representation of the UI we’re building out:

    449e4294-8917-470e-ad06-cf54d1809296

    Creating the Color Palette Section

    To display all the colors provided in our colorOptions array, we need to first map through the array consisting of color values and render a <div> for each color.

    Each <div>:

    • Acts as a draggable color block with fixed width and height.

    • Has a semi-circular appearance using Tailwind CSS classes and inline styling to apply the specific background color.

    • Triggers the handleDragStart function when dragging begins, passing the event and the selected color.

    • Has a unique key for React’s rendering optimization.

    • If the color is white (#ffffff), it conditionally displays the text “White” in light gray for visibility.

    This setup allows users to visually identify and drag different color options to the top or bottom of an outfit on the UI.

    return (
      <div className="flex flex-col items-center p-6 bg-gray-100 rounded-lg min-h-screen">
        <h1 className="text-3xl font-extrabold mb-8 text-indigo-700">
          Dynamic Wardrobe
        </h1>
    
        <div className="flex flex-col md:flex-row w-full gap-8">
          {/* Color palette section */}
          <div className="w-full md:w-1/3 bg-white p-6 rounded-lg shadow-md">
            <h2 className="text-xl font-semibold mb-4 text-center">
              Color Palette
            </h2>
            <p className="mb-4 text-sm text-gray-600">
              Drag colors to the outfit pieces
            </p>
            <div className="grid grid-cols-5 gap-2">
              {colorOptions.map((color) => (
                <div
                  key={color}
                  className="w-12 h-12 rounded-md shadow-sm cursor-move flex items-center justify-center"
                  style={{ backgroundColor: color, border: "1px solid #ddd" }}
                  draggable="true"
                  onDragStart={(e) => handleDragStart(e, color)}
                >
                  {color === "#ffffff" && (
                    <span className="text-xs text-gray-400">White</span>
                  )}
                </div>
              ))}
            </div>
          </div>
        </div>
      </div>
    );
    

    Creating the Outfit Preview

    Finally, let’s implement the outfit preview section, which is the fun part. There are two parts to the outfit display: the top and the bottom section. Let’s look at them one after the other:

    Top Section

    This section acts as a drop target for the top clothing color. It consists of a div with an SVG that allows for color filling.

    <div
      className="w-full flex items-center justify-center"
      onDrop={handleDropOnTop}
      onDragOver={allowDrop}
    >
      {/* T-shirt */}
      <svg viewBox="0 0 24 24" width="180" height="140">
        <path
          d="M16 2H8L6 6v3h2v13h8V9h2V6l-2-4z"
          fill={selectedTop}
          stroke="#333"
          strokeWidth="0.2"
        />
      </svg>
    </div>;
    

    In this section:

    • onDrop={handleDropOnTop}: Sets the top outfit color, when a color is dropped at the top div.

    • allowDrop is called via onDragOver to enable dropping.

    • The T-shirt SVG is drawn and its fill color is controlled by selectedTop, which updates when a new color is dropped.

    Bottom Section

    This section acts as a drop target for the bottom clothing color. It consists of a div with an SVG that allows for color filling.

    <div
      className="w-full flex items-center justify-center -mt-8"
      onDrop={handleDropOnBottom}
      onDragOver={allowDrop}
    >
      <svg viewBox="0 0 200 200" width="120" height="140">
        {/* Pants */}
        <path
          d="M60,20 L140,20 L150,180 L110,180 L100,100 L90,180 L50,180 L60,20 Z"
          fill={selectedBottom}
          stroke="#333"
          strokeWidth="2"
        />
        {/* Waistband */}
        <rect x="60" y="18" width="80" height="5" fill="#444" />
        {/* Center seam */}
        <path d="M100,20 L100,100" stroke="#000" strokeWidth="1" />
      </svg>
    </div>;
    

    In this section:

    • onDrop={handleDropOnBottom}: Sets the bottom outfit color, when a color is dropped at the bottom div.

    • allowDrop is called via onDragOver to enable dropping.

    • The pant SVG is drawn and its fill color is controlled by selectedBottom, which updates when a new color is dropped.

    • Extra details like a waistband (rect) and a seam (path) add realism.

    That completes the UI section of our project.

    Step 6: Putting It All Together

    Now that you’ve learned about the integral aspects, here is the full code that will give you the entire look and functionality:

    import { useState } from "react";
    
    export default function App() {
      // State for selected colors
      const [selectedTop, setSelectedTop] = useState("#ffffff");
      const [selectedBottom, setSelectedBottom] = useState("#ffffff");
    
      // Color options for clothing
      const colorOptions = [
        "#ff0000", // Red
        "#0000ff", // Blue
        "#ffff00", // Yellow
        "#00ff00", // Green
        "#ff00ff", // Pink
        "#808080", // Gray
        "#000000", // Black
        "#ffffff", // White
        "#ffa500", // Orange
        "#800080", // Purple
        "#8B0000", // Dark Red
        "#006400", // Dark Green
        "#00008B", // Dark Blue
        "#4B0082", // Indigo
        "#228B22", // Forest Green
        "#20B2AA", // Light Sea Green
        "#87CEEB", // Sky Blue
        "#4682B4", // Steel Blue
        "#9932CC", // Dark Orchid
        "#FF1493", // Deep Pink
        "#FF4500", // Orange Red
        "#FFD700", // Gold
        "#F0E68C", // Khaki
        "#F5DEB3", // Wheat
        "#D2B48C", // Tan
        "#A0522D", // Sienna
        "#8B4513", // Saddle Brown
        "#BC8F8F", // Rosy Brown
        "#708090", // Slate Gray
        "#2F4F4F", // Dark Slate Gray
      ];
    
      // Drag and drop handlers
      const handleDragStart = (e, color) => {
        e.dataTransfer.setData("color", color);
      };
    
      const handleDropOnTop = (e) => {
        e.preventDefault();
        const color = e.dataTransfer.getData("color");
        setSelectedTop(color);
      };
    
      const handleDropOnBottom = (e) => {
        e.preventDefault();
        const color = e.dataTransfer.getData("color");
        setSelectedBottom(color);
      };
    
      const allowDrop = (e) => {
        e.preventDefault();
      };
    
      return (
        <div className="flex flex-col items-center p-6 bg-gray-100 rounded-lg min-h-screen">
          <h1 className="text-3xl font-extrabold mb-8 text-indigo-700">
            Dynamic Wardrobe
          </h1>
    
          <div className="flex flex-col md:flex-row w-full gap-8">
            {/* Color palette section */}
            <div className="w-full md:w-1/3 bg-white p-6 rounded-lg shadow-md">
              <h2 className="text-xl font-semibold mb-4 text-center">
                Color Palette
              </h2>
              <p className="mb-4 text-sm text-gray-600">
                Drag colors to the outfit pieces
              </p>
              <div className="grid grid-cols-5 gap-2">
                {colorOptions.map((color) => (
                  <div
                    key={color}
                    className="w-12 h-12 rounded-md shadow-sm cursor-move flex items-center justify-center"
                    style={{ backgroundColor: color, border: "1px solid #ddd" }}
                    draggable="true"
                    onDragStart={(e) => handleDragStart(e, color)}
                  >
                    {color === "#ffffff" && (
                      <span className="text-xs text-gray-400">White</span>
                    )}
                  </div>
                ))}
              </div>
            </div>
    
            {/* Outfit visualization section */}
            <div className="w-full md:w-2/3 bg-white p-6 rounded-lg shadow-md">
              <h2 className="text-xl font-semibold mb-4 text-center">
                Outfit Preview
              </h2>
              <div className="flex flex-col items-center">
                <div className="relative w-64 h-64">
                  {/* Outfit container - better positioning */}
                  <div className="relative w-full h-full flex flex-col items-center justify-center">
                    {/* Top Section - accepts drag and drop */}
                    <div
                      className="w-full flex items-center justify-center"
                      onDrop={handleDropOnTop}
                      onDragOver={allowDrop}
                    >
                      {/* T-shirt */}
                      <svg viewBox="0 0 24 24" width="180" height="140">
                        <path
                          d="M16 2H8L6 6v3h2v13h8V9h2V6l-2-4z"
                          fill={selectedTop}
                          stroke="#333"
                          strokeWidth="0.2"
                        />
                      </svg>
                    </div>
                    <div
                      className="w-full flex items-center justify-center -mt-8"
                      onDrop={handleDropOnBottom}
                      onDragOver={allowDrop}
                    >
                      <svg viewBox="0 0 200 200" width="120" height="140">
                        {/* Pants */}
                        <path
                          d="M60,20 L140,20 L150,180 L110,180 L100,100 L90,180 L50,180 L60,20 Z"
                          fill={selectedBottom}
                          stroke="#333"
                          strokeWidth="2"
                        />
                        {/* Waistband */}
                        <rect x="60" y="18" width="80" height="5" fill="#444" />
                        {/* Center seam */}
                        <path d="M100,20 L100,100" stroke="#000" strokeWidth="1" />
                      </svg>
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
      );
    }
    

    Here’s our dynamic wardrobe in full flow:

    e840ecd6-665f-41b4-a590-02e91302cf26

    Conclusion

    This dynamic wardrobe project demonstrates the power of React’s drag and drop API combined with state management. Not only is it a fun project to build, but it also taught you important concepts like managing state in React components, implementing drag and drop functionality, creating responsive layouts with Tailwind CSS and using SVG for interactive visuals.

    If you enjoyed reading this tutorial, you could Buy Me a Coffee. You can also connect with me on LinkedIn for more programming-related posts and articles.

    See you on the next one!

    Source: freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More 

    Facebook Twitter Reddit Email Copy Link
    Previous ArticleImprove you C++ skills by coding an audio plugin
    Next Article Bungie vaulting Destiny 2 content backfires with the latest Red War lawsuit court ruling

    Related Posts

    Development

    GPT-5 is Coming: Revolutionizing Software Testing

    July 22, 2025
    Development

    Win the Accessibility Game: Combining AI with Human Judgment

    July 22, 2025
    Leave A Reply Cancel Reply

    For security, use of Google's reCAPTCHA service is required which is subject to the Google Privacy Policy and Terms of Use.

    Continue Reading

    Apple introduces a delightful and elegant new software design

    Web Development

    Escritoire creates standards-compliant letters

    Linux

    CSG waarschuwt voor kritiek beveiligingslek in NetScaler Gateway en ADC

    Security

    CVE-2025-41444 – Zohocorp ManageEngine ADAudit Plus SQL Injection Vulnerability

    Common Vulnerabilities and Exposures (CVEs)

    Highlights

    CVE-2025-30202 – vLLM ZeroMQ Denial of Service and Data Exposure Vulnerability

    April 30, 2025

    CVE ID : CVE-2025-30202

    Published : April 30, 2025, 1:15 a.m. | 1 hour, 52 minutes ago

    Description : vLLM is a high-throughput and memory-efficient inference and serving engine for LLMs. Versions starting from 0.5.2 and prior to 0.8.5 are vulnerable to denial of service and data exposure via ZeroMQ on multi-node vLLM deployment. In a multi-node vLLM deployment, vLLM uses ZeroMQ for some multi-node communication purposes. The primary vLLM host opens an XPUB ZeroMQ socket and binds it to ALL interfaces. While the socket is always opened for a multi-node deployment, it is only used when doing tensor parallelism across multiple hosts. Any client with network access to this host can connect to this XPUB socket unless its port is blocked by a firewall. Once connected, these arbitrary clients will receive all of the same data broadcasted to all of the secondary vLLM hosts. This data is internal vLLM state information that is not useful to an attacker. By potentially connecting to this socket many times and not reading data published to them, an attacker can also cause a denial of service by slowing down or potentially blocking the publisher. This issue has been patched in version 0.8.5.

    Severity: 7.5 | HIGH

    Visit the link for more details, such as CVSS details, affected products, timeline, and more…

    Designer Spotlight: Stephanie Bruce

    April 18, 2025

    CVE-2025-37988 – Apache Linux Kernel Mount Namespace Locking races

    May 20, 2025

    New method assesses and improves the reliability of radiologists’ diagnostic reports

    April 4, 2025
    © DevStackTips 2025. All rights reserved.
    • Contact
    • Privacy Policy

    Type above and press Enter to search. Press Esc to cancel.