Build & Deploy Ecommerce Website Using React & TaiwindCSS | Step-by-Step Tutorial

Welcome to my website U-GINE MEDIA. In this website I teach tutorials and share source code on some programming (HTML, CSS, JavaScript, React) tutorials. 

Before we get started, do well to subscribe to my channel to never miss out on any update that I post every single day.

You can also visit my GitHub where I upload all the code I have.

In this tutorial topic "Build & Deploy Ecommerce Website Using React & TaiwindCSS | Step-by-Step Tutorial", we will learn how to create it following these simple easy steps.

Share this to your programmer friends. If y'all learnt something today, make sure to let me in the comments. 

Get Source Code.

If interested in watching the video before running the code below, you can click the play button to get started.



Setting Up the Project

Before building the "an Ecommerce Website" with React.js and CSS, ensure Node.js is installed on your computer. If not, download and install it from the official Node.js website.

Create a Project Folder:

  1. Make a new folder, for instance, “ecommerce-website”.
  2. Open this folder in your VS Code editor.

Initialize the Project:

Open your terminal by pressing Ctrl + J and then use Vite to create a new React app with this command:

  npm create vite@latest ./ -- --template react


Install necessary dependencies and start the development server:

npm install

Install the following dependcies: 
  • TailwindCSS
  • React Icons

Run your development server:

npm run dev


If your project is running in your browser, congratulations! You’ve successfully set up your app. Now, let’s move on to modifying folders and files.

Modify folder and CSS Files:

  1. Remove the default assets folder and App.css file.
  2. Replace the content of index.css with the provided CSS code.

@import "tailwindcss";
  
  
  

Creating the Components

Within the src directory of your project, organize your files by creating a “components” folder. Inside the components folder, create the following files:
  1. CollectionSlider.jsx
  2. FilterBar.jsx
  3. Footer.jsx
  4. Header.jsx
  5. Hero.jsx
  6. ProductGrid.jsx
  7. ShoppingCart.jsx

Adding the Codes

Add the respective code to each newly created file to define the layout.

In src/component/CollectionSlider.jsx, add the code.

import React from 'react'
import collection1 from "../assets/collection-1.jpg";
import collection2 from "../assets/collection-2.jpg";

const CollectionSlider = () => {
const collections = [
    {
    image: collection1,
    hashtag: '#MILANCE',
    text: 'Quisquemos sodales suscipit ditaemcos lorem de cosmo lacus meleifend menean...'
  },
  {
    image: collection2,
    hashtag: '#CONVALIS',
    text: 'Quisquemos sodales suscipit ditaemcos lorem de cosmo lacus meleifend menean...'
  }
];

return (
    <>
        <div className="flex flex-wrap justify-center gap-4 py-12 px-8">
            {/* Left Product Image */}
            <img
                src={collections[0].image}
                alt="model-1"
                className="md:w-72 w-full h-auto object-cover"
            />

            {/* Collection Card 1 */}
            <div className="border p-6 text-center md:w-72 w-full flex flex-col justify-between">
                <p className="text-gray-500 text-sm uppercase">New Collection</p>
                <h2 className="text-2xl font-bold my-2">{collections[0].hashtag}</h2>
                <p className="text-gray-600 text-sm mb-4">{collections[0].text}</p>
                <button className="bg-gray-600 text-white px-4 py-2 font-semibold cursor-pointer transition duration-300 hover:bg-gray-700">
                    SHOP NOW
                </button>
            </div>

            {/* Right Product Image */}
            <img
                src={collections[1].image}
                alt="model-2"
                className="md:w-72 w-full h-auto object-cover"
            />

            {/* Collection Card 2 */}
            <div className="border p-6 text-center md:w-72 w-full flex flex-col justify-between">
                <p className="text-gray-500 text-sm uppercase">New Collection</p>
                <h2 className="text-2xl font-bold my-2">{collections[1].hashtag}</h2>
                <p className="text-gray-600 text-sm mb-4">{collections[1].text}</p>
                <button className="bg-gray-600 text-white px-4 py-2 font-semibold cursor-pointer transition duration-300 hover:bg-gray-700">
                    SHOP NOW
                </button>
            </div>
        </div>
        <p className="px-4 sm:px-8 text-sm md:text-base max-w-3xl w-full mx-auto text-center text-gray-600 my-14">
            Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis risus leo, elementum in malesuada an darius ut augue. Cras sit amet lectus et justo feugiat euismod sed non erat. Nulla non felis id metus bibendum iaculis quis sit amet eros. Nam suscipit mollis tellus vel malesuada. Duis danos an molestie, sem in sollicitudin sodales mi justo sagittis est id consequat ipsum ligula a milance de mante...
        </p>
    </>
)
}

export default CollectionSlider





In src/component/FilterBar.jsx, add the code.

import React from 'react'
import { GoChevronDown } from "react-icons/go";


const options = {
  Price: ['Under $50', '$50 - $100', '$100 - $200', 'Above $200'],
  'Product Type': ['T-Shirts', 'Jeans', 'Sneakers', 'Accessories'],
  Brand: ['Nike', 'Adidas', 'Zara', 'Puma'],
  Availability: ['In Stock', 'Out of Stock'],
  Color: ['Black', 'White', 'Red', 'Blue'],
  Size: ['Small', 'Medium', 'Large', 'XL'],
};

const SelectBox = ({ label, items }) => (
  <div className="relative">
    <select
      className="appearance-none border border-gray-300 rounded px-4 pr-10 py-2 bg-white text-sm focus:outline-none cursor-pointer"
      defaultValue=""
    >
      <option value="" disabled>{label}</option>
      {items.map((item, idx) => (
        <option key={idx} value={item}>{item}</option>
      ))}
    </select>
    <GoChevronDown className="w-4 h-4 absolute right-3 top-1/2 transform -translate-y-1/2 text-gray-400 pointer-events-none" />
  </div>
);

const FilterBar = () => {
  return (
    <div className="py-12 flex items-center justify-center flex-wrap gap-10 p-4 bg-white border-b border-gray-300 mb-10">
      {Object.entries(options).map(([label, items]) => (
        <SelectBox key={label} label={label} items={items} />
      ))}
    </div>
  )
}

export default FilterBar





In src/component/Footer.jsx, add the code.

import React, {useState} from 'react'
import { FaFacebookF, FaInstagram, FaPinterestP, FaYoutube, FaTiktok, FaTimes} from 'react-icons/fa';
import { GoPlus } from "react-icons/go";
import { HiMinus } from "react-icons/hi2";

const FooterSection = ({ title, links }) => {
  const [isOpen, setIsOpen] = useState(false);

  return (
    <div className="w-full md:w-auto mb-6 md:mb-0">
      <div
        className="flex justify-between items-center md:block cursor-pointer"
        onClick={() => setIsOpen(!isOpen)}
      >
        <h3 className="text-white font-semibold uppercase tracking-wide text-sm mb-2 md:mb-4">
          {title}
        </h3>
        <span className="text-white md:hidden">{isOpen ? <HiMinus /> : <GoPlus />}</span>
      </div>
      <ul
        className={`md:block ${isOpen ? 'block' : 'hidden'} text-sm text-gray-400 space-y-2`}
      >
        {links.map((link, idx) => (
          <li key={idx} className="hover:text-white cursor-pointer">{link}</li>
        ))}
      </ul>
    </div>
  );
};


const Footer = () => {
  return (
     <footer className="bg-black text-white text-sm px-6 py-12 mt-36">
      <div className="max-w-screen-xl mx-auto">
        {/* Top Section */}
        <div className="flex flex-col md:flex-row justify-between gap-8">
          <FooterSection
            title="Shop"
            links={[
              'New In', 'Women', 'Men', 'Shoes',
              'Bags & Accessories', 'Top Brands', 'Sale & Special Offers'
            ]}
          />
          <FooterSection
            title="Information"
            links={[ 'About', 'Blog' ]}
          />
          <FooterSection
            title="Customer Service"
            links={[
              'Search Terms', 'Advanced Search', 'Orders And Returns',
              'Contact Us', 'Theme FAQs', 'Consultant', 'Store Locations'
            ]}
          />
          <div className="w-full md:w-auto">
            <h3 className="text-white font-semibold uppercase tracking-wide text-sm mb-2 md:mb-4">
              Newsletter Sign Up
            </h3>
            <p className="text-gray-400 mb-4">
              Sign up for exclusive updates, new arrivals & insider only discounts
            </p>
            <div className="flex">
              <input
                type="text"
                placeholder="enter your email address"
                className="px-4 py-2 flex-1 border border-gray-700 bg-black text-white placeholder-gray-500"
              />
              <button className="bg-white text-black font-semibold px-4 cursor-pointer">SUBMIT</button>
            </div>
            <div className="flex space-x-4 mt-4">
              <FaFacebookF className="bg-white text-black rounded-full p-2 w-8 h-8 cursor-pointer" />
              <FaInstagram className="bg-white text-black rounded-full p-2 w-8 h-8 cursor-pointer" />
              <FaPinterestP className="bg-white text-black rounded-full p-2 w-8 h-8 cursor-pointer" />
              <FaTiktok className="bg-white text-black rounded-full p-2 w-8 h-8 cursor-pointer" />
              <FaYoutube className="bg-white text-black rounded-full p-2 w-8 h-8 cursor-pointer" />
              <FaTimes className="bg-white text-black rounded-full p-2 w-8 h-8 cursor-pointer" />
            </div>
          </div>
        </div>

        {/* Bottom Section */}
        <div className="mt-10 border-t border-gray-700 pt-6 flex flex-col md:flex-row justify-between items-center">
          <p className="text-gray-500 text-center md:text-left mb-4 md:mb-0">
            &copy; {new Date().getFullYear()}, Website Demo. All Rights Reserved. Themes By U-GINE MEDIA
          </p>
          <div className="flex space-x-2">
            {/* Visa Card */}
            <svg className="icon icon--full-color cursor-pointer" viewBox="0 0 38 24" xmlns="http://www.w3.org/2000/svg" role="img" width="38" height="24" aria-labelledby="pi-visa"><title id="pi-visa">Visa</title><path opacity=".07" d="M35 0H3C1.3 0 0 1.3 0 3v18c0 1.7 1.4 3 3 3h32c1.7 0 3-1.3 3-3V3c0-1.7-1.4-3-3-3z"></path><path fill="#fff" d="M35 1c1.1 0 2 .9 2 2v18c0 1.1-.9 2-2 2H3c-1.1 0-2-.9-2-2V3c0-1.1.9-2 2-2h32"></path><path d="M28.3 10.1H28c-.4 1-.7 1.5-1 3h1.9c-.3-1.5-.3-2.2-.6-3zm2.9 5.9h-1.7c-.1 0-.1 0-.2-.1l-.2-.9-.1-.2h-2.4c-.1 0-.2 0-.2.2l-.3.9c0 .1-.1.1-.1.1h-2.1l.2-.5L27 8.7c0-.5.3-.7.8-.7h1.5c.1 0 .2 0 .2.2l1.4 6.5c.1.4.2.7.2 1.1.1.1.1.1.1.2zm-13.4-.3l.4-1.8c.1 0 .2.1.2.1.7.3 1.4.5 2.1.4.2 0 .5-.1.7-.2.5-.2.5-.7.1-1.1-.2-.2-.5-.3-.8-.5-.4-.2-.8-.4-1.1-.7-1.2-1-.8-2.4-.1-3.1.6-.4.9-.8 1.7-.8 1.2 0 2.5 0 3.1.2h.1c-.1.6-.2 1.1-.4 1.7-.5-.2-1-.4-1.5-.4-.3 0-.6 0-.9.1-.2 0-.3.1-.4.2-.2.2-.2.5 0 .7l.5.4c.4.2.8.4 1.1.6.5.3 1 .8 1.1 1.4.2.9-.1 1.7-.9 2.3-.5.4-.7.6-1.4.6-1.4 0-2.5.1-3.4-.2-.1.2-.1.2-.2.1zm-3.5.3c.1-.7.1-.7.2-1 .5-2.2 1-4.5 1.4-6.7.1-.2.1-.3.3-.3H18c-.2 1.2-.4 2.1-.7 3.2-.3 1.5-.6 3-1 4.5 0 .2-.1.2-.3.2M5 8.2c0-.1.2-.2.3-.2h3.4c.5 0 .9.3 1 .8l.9 4.4c0 .1 0 .1.1.2 0-.1.1-.1.1-.1l2.1-5.1c-.1-.1 0-.2.1-.2h2.1c0 .1 0 .1-.1.2l-3.1 7.3c-.1.2-.1.3-.2.4-.1.1-.3 0-.5 0H9.7c-.1 0-.2 0-.2-.2L7.9 9.5c-.2-.2-.5-.5-.9-.6-.6-.3-1.7-.5-1.9-.5L5 8.2z" fill="#142688"></path></svg>

            {/* Mastercard */}
            <svg className="icon icon--full-color cursor-pointer" viewBox="0 0 38 24" xmlns="http://www.w3.org/2000/svg" role="img" width="38" height="24" aria-labelledby="pi-master"><title id="pi-master">Mastercard</title><path opacity=".07" d="M35 0H3C1.3 0 0 1.3 0 3v18c0 1.7 1.4 3 3 3h32c1.7 0 3-1.3 3-3V3c0-1.7-1.4-3-3-3z"></path><path fill="#fff" d="M35 1c1.1 0 2 .9 2 2v18c0 1.1-.9 2-2 2H3c-1.1 0-2-.9-2-2V3c0-1.1.9-2 2-2h32"></path><circle fill="#EB001B" cx="15" cy="12" r="7"></circle><circle fill="#F79E1B" cx="23" cy="12" r="7"></circle><path fill="#FF5F00" d="M22 12c0-2.4-1.2-4.5-3-5.7-1.8 1.3-3 3.4-3 5.7s1.2 4.5 3 5.7c1.8-1.2 3-3.3 3-5.7z"></path></svg>
            <svg className="icon icon--full-color cursor-pointer" viewBox="0 0 38 24" xmlns="http://www.w3.org/2000/svg" width="38" height="24" role="img" aria-labelledby="pi-maestro"><title id="pi-maestro">Maestro</title><path opacity=".07" d="M35 0H3C1.3 0 0 1.3 0 3v18c0 1.7 1.4 3 3 3h32c1.7 0 3-1.3 3-3V3c0-1.7-1.4-3-3-3z"></path><path fill="#fff" d="M35 1c1.1 0 2 .9 2 2v18c0 1.1-.9 2-2 2H3c-1.1 0-2-.9-2-2V3c0-1.1.9-2 2-2h32"></path><circle fill="#EB001B" cx="15" cy="12" r="7"></circle><circle fill="#00A2E5" cx="23" cy="12" r="7"></circle><path fill="#7375CF" d="M22 12c0-2.4-1.2-4.5-3-5.7-1.8 1.3-3 3.4-3 5.7s1.2 4.5 3 5.7c1.8-1.2 3-3.3 3-5.7z"></path></svg>

            {/* Apple Card */}
            <svg className="icon icon--full-color cursor-pointer" version="1.1" xmlns="http://www.w3.org/2000/svg" role="img" x="0" y="0" width="38" height="24" viewBox="0 0 165.521 105.965" xmlSpace="preserve" aria-labelledby="pi-apple_pay"><title id="pi-apple_pay">Apple Pay</title><path fill="#000" d="M150.698 0H14.823c-.566 0-1.133 0-1.698.003-.477.004-.953.009-1.43.022-1.039.028-2.087.09-3.113.274a10.51 10.51 0 0 0-2.958.975 9.932 9.932 0 0 0-4.35 4.35 10.463 10.463 0 0 0-.975 2.96C.113 9.611.052 10.658.024 11.696a70.22 70.22 0 0 0-.022 1.43C0 13.69 0 14.256 0 14.823v76.318c0 .567 0 1.132.002 1.699.003.476.009.953.022 1.43.028 1.036.09 2.084.275 3.11a10.46 10.46 0 0 0 .974 2.96 9.897 9.897 0 0 0 1.83 2.52 9.874 9.874 0 0 0 2.52 1.83c.947.483 1.917.79 2.96.977 1.025.183 2.073.245 3.112.273.477.011.953.017 1.43.02.565.004 1.132.004 1.698.004h135.875c.565 0 1.132 0 1.697-.004.476-.002.952-.009 1.431-.02 1.037-.028 2.085-.09 3.113-.273a10.478 10.478 0 0 0 2.958-.977 9.955 9.955 0 0 0 4.35-4.35c.483-.947.789-1.917.974-2.96.186-1.026.246-2.074.274-3.11.013-.477.02-.954.022-1.43.004-.567.004-1.132.004-1.699V14.824c0-.567 0-1.133-.004-1.699a63.067 63.067 0 0 0-.022-1.429c-.028-1.038-.088-2.085-.274-3.112a10.4 10.4 0 0 0-.974-2.96 9.94 9.94 0 0 0-4.35-4.35A10.52 10.52 0 0 0 156.939.3c-1.028-.185-2.076-.246-3.113-.274a71.417 71.417 0 0 0-1.431-.022C151.83 0 151.263 0 150.698 0z"></path><path fill="#FFF" d="M150.698 3.532l1.672.003c.452.003.905.008 1.36.02.793.022 1.719.065 2.583.22.75.135 1.38.34 1.984.648a6.392 6.392 0 0 1 2.804 2.807c.306.6.51 1.226.645 1.983.154.854.197 1.783.218 2.58.013.45.019.9.02 1.36.005.557.005 1.113.005 1.671v76.318c0 .558 0 1.114-.004 1.682-.002.45-.008.9-.02 1.35-.022.796-.065 1.725-.221 2.589a6.855 6.855 0 0 1-.645 1.975 6.397 6.397 0 0 1-2.808 2.807c-.6.306-1.228.511-1.971.645-.881.157-1.847.2-2.574.22-.457.01-.912.017-1.379.019-.555.004-1.113.004-1.669.004H14.801c-.55 0-1.1 0-1.66-.004a74.993 74.993 0 0 1-1.35-.018c-.744-.02-1.71-.064-2.584-.22a6.938 6.938 0 0 1-1.986-.65 6.337 6.337 0 0 1-1.622-1.18 6.355 6.355 0 0 1-1.178-1.623 6.935 6.935 0 0 1-.646-1.985c-.156-.863-.2-1.788-.22-2.578a66.088 66.088 0 0 1-.02-1.355l-.003-1.327V14.474l.002-1.325a66.7 66.7 0 0 1 .02-1.357c.022-.792.065-1.717.222-2.587a6.924 6.924 0 0 1 .646-1.981c.304-.598.7-1.144 1.18-1.623a6.386 6.386 0 0 1 1.624-1.18 6.96 6.96 0 0 1 1.98-.646c.865-.155 1.792-.198 2.586-.22.452-.012.905-.017 1.354-.02l1.677-.003h135.875"></path><g><g><path fill="#000" d="M43.508 35.77c1.404-1.755 2.356-4.112 2.105-6.52-2.054.102-4.56 1.355-6.012 3.112-1.303 1.504-2.456 3.959-2.156 6.266 2.306.2 4.61-1.152 6.063-2.858"></path><path fill="#000" d="M45.587 39.079c-3.35-.2-6.196 1.9-7.795 1.9-1.6 0-4.049-1.8-6.698-1.751-3.447.05-6.645 2-8.395 5.1-3.598 6.2-.95 15.4 2.55 20.45 1.699 2.5 3.747 5.25 6.445 5.151 2.55-.1 3.549-1.65 6.647-1.65 3.097 0 3.997 1.65 6.696 1.6 2.798-.05 4.548-2.5 6.247-5 1.95-2.85 2.747-5.6 2.797-5.75-.05-.05-5.396-2.101-5.446-8.251-.05-5.15 4.198-7.6 4.398-7.751-2.399-3.548-6.147-3.948-7.447-4.048"></path></g><g><path fill="#000" d="M78.973 32.11c7.278 0 12.347 5.017 12.347 12.321 0 7.33-5.173 12.373-12.529 12.373h-8.058V69.62h-5.822V32.11h14.062zm-8.24 19.807h6.68c5.07 0 7.954-2.729 7.954-7.46 0-4.73-2.885-7.434-7.928-7.434h-6.706v14.894z"></path><path fill="#000" d="M92.764 61.847c0-4.809 3.665-7.564 10.423-7.98l7.252-.442v-2.08c0-3.04-2.001-4.704-5.562-4.704-2.938 0-5.07 1.507-5.51 3.82h-5.252c.157-4.86 4.731-8.395 10.918-8.395 6.654 0 10.995 3.483 10.995 8.89v18.663h-5.38v-4.497h-.13c-1.534 2.937-4.914 4.782-8.579 4.782-5.406 0-9.175-3.222-9.175-8.057zm17.675-2.417v-2.106l-6.472.416c-3.64.234-5.536 1.585-5.536 3.95 0 2.288 1.975 3.77 5.068 3.77 3.95 0 6.94-2.522 6.94-6.03z"></path><path fill="#000" d="M120.975 79.652v-4.496c.364.051 1.247.103 1.715.103 2.573 0 4.029-1.09 4.913-3.899l.52-1.663-9.852-27.293h6.082l6.863 22.146h.13l6.862-22.146h5.927l-10.216 28.67c-2.34 6.577-5.017 8.735-10.683 8.735-.442 0-1.872-.052-2.261-.157z"></path></g></g></svg>

            {/* Bitcoin */}
            <svg className="icon icon--full-color cursor-pointer" viewBox="0 0 38 24" xmlns="http://www.w3.org/2000/svg" width="38" height="24" role="img" aria-labelledby="pi-bitcoin"><title id="pi-bitcoin">Bitcoin</title><path opacity=".07" d="M35 0H3C1.3 0 0 1.3 0 3v18c0 1.7 1.4 3 3 3h32c1.7 0 3-1.3 3-3V3c0-1.7-1.4-3-3-3z"></path><path fill="#fff" d="M35 1c1.1 0 2 .9 2 2v18c0 1.1-.9 2-2 2H3c-1.1 0-2-.9-2-2V3c0-1.1.9-2 2-2h32"></path><path fill="#EDA024" d="M21.6 4.4c-4.2-1.4-8.7.8-10.2 5s.8 8.7 5 10.2 8.7-.8 10.2-5c1.4-4.2-.8-8.7-5-10.2z"></path><path fill="#fff" d="M16.1 8.3l.3-1c.6.2 1.3.4 1.9.7.2-.5.4-1 .5-1.6l.9.3-.5 1.5.8.3.5-1.5.9.3c-.2.5-.4 1-.5 1.6l.4.2c.3.2.6.4.9.7.3.3.4.6.5 1 0 .3 0 .6-.2.9-.2.5-.5.8-1.1.9h-.2c.2.1.3.2.4.4.4.4.5.8.4 1.4 0 .1 0 .2-.1.3 0 .1 0 .1-.1.2-.1.2-.2.3-.2.5-.3.5-.8.9-1.5.9-.5 0-1 0-1.4-.1l-.4-.1c-.2.5-.4 1-.5 1.6l-.9-.3c.2-.5.4-1 .5-1.5l-.8-.3c-.2.5-.4 1-.5 1.5l-.9-.3c.2-.5.4-1 .5-1.6l-1.9-.6.6-1.1c.2.1.5.2.7.2.2.1.4 0 .5-.2L17 9.3v-.1c0-.3-.1-.5-.4-.5 0-.2-.2-.3-.5-.4zm1.2 6c.5.2.9.3 1.3.4.3.1.5.1.8.1.2 0 .3 0 .5-.1.5-.3.6-1 .2-1.4l-.6-.5c-.3-.2-.7-.3-1.1-.4-.1 0-.3-.1-.4-.2l-.7 2.1zm1-3.1c.3.1.5.2.7.2.3.1.6.2.9.1.4 0 .7-.1.8-.5.1-.3.1-.6 0-.8-.1-.2-.3-.3-.5-.4-.3-.2-.6-.3-1-.4l-.3-.1c-.1.7-.4 1.3-.6 1.9z"></path></svg>
          </div>
        </div>
      </div>
    </footer>
  )
}

export default Footer




In src/component/Header.jsx, add the code.

import React, {useState} from 'react'
import { IoCartOutline } from "react-icons/io5";
import { MdChevronRight } from "react-icons/md";
import { IoIosMenu } from "react-icons/io";
import { IoMdClose } from "react-icons/io";

// Importing the shopping cart component
import ShoppingCart from './ShoppingCart';

const Header = () => {
  const [openMenu, setOpenMenu] = useState(null);

  const toggleMenu = (menu) => {
    setOpenMenu(openMenu === menu ? null : menu);
  };

  // State to manage cart visibility
  const [isCartOpen, setIsCartOpen] = useState(false);

return (
    <>
    <header className="flex justify-between items-center px-6 py-4 bg-transparent text-black uppercase">
        <a href='' className="text-2xl font-bold">FabrikFit</a>

        {/* Mobile menu button */}
        <button
            className="lg:hidden flex items-center px-2 py-1 border rounded text-black border-gray-400 cursor-pointer"
            onClick={() => toggleMenu('mobile')}
        >
            <IoIosMenu className="text-3xl" />
        </button>

        {/* Desktop nav */}
        <nav className="hidden lg:block relative">
            <ul className="flex gap-6 font-medium">
                <li className="cursor-pointer hover:text-indigo-700">Home</li>

                {/* SHOP DROPDOWN */}
                <li className="group relative cursor-pointer">
                    <span className="hover:text-indigo-700">Shop</span>
                    <ul className="absolute left-0 top-full mt-2 w-48 bg-white text-black rounded-md shadow-lg opacity-0 group-hover:opacity-100 group-hover:visible invisible transition-all duration-300 z-50">
                        <li className="px-4 py-2 hover:bg-gray-100 hover:text-indigo-700 overflow-hidden">Men</li>
                        <li className="px-4 py-2 hover:bg-gray-100 hover:text-indigo-700">Women</li>

                        {/* Submenu */}
                        <li className="relative group/submenu">
                            <span className="px-4 py-2 flex items-center justify-between hover:bg-gray-100 hover:text-indigo-700">Accessories <MdChevronRight /></span>
                            <ul className="absolute left-full top-0 ml-1 w-44 bg-white text-black rounded-md shadow-lg opacity-0 group-hover/submenu:opacity-100 group-hover/submenu:visible invisible transition-all duration-300 z-50">
                                <li className="px-4 py-2 hover:bg-gray-100 hover:text-indigo-700">Chargers</li>
                                <li className="px-4 py-2 hover:bg-gray-100 hover:text-indigo-700">Cables</li>
                                <li className="px-4 py-2 hover:bg-gray-100 hover:text-indigo-700">Headphones</li>
                            </ul>
                        </li>
                    </ul>
                </li>

                {/* COLLECTIONS DROPDOWN */}
                <li className="group relative cursor-pointer">
                    <span className="hover:text-indigo-700">Collections</span>
                    <ul className="absolute left-0 top-full mt-2 w-56 bg-white text-black rounded-md shadow-lg opacity-0 group-hover:opacity-100 group-hover:visible invisible transition-all duration-300 z-50">
                        <li className="px-4 py-2 hover:bg-gray-100 hover:text-indigo-700">Essentials</li>
                        <li className="px-4 py-2 hover:bg-gray-100 hover:text-indigo-700">Streetwear</li>
                        <li className="px-4 py-2 hover:bg-gray-100 hover:text-indigo-700">Workwear</li>
                    </ul>
                </li>

                <li className="cursor-pointer hover:text-indigo-700">LookBook</li>
                <li className="cursor-pointer hover:text-indigo-700">Contact</li>
            </ul>
        </nav>

        {/* Mobile nav */}
        {openMenu === 'mobile' && (
            <nav className="lg:hidden fixed inset-0 bg-gray-950 z-50 flex flex-col">
                <div className="bg-white w-3/4 max-w-xs h-full p-6 shadow-lg overflow-y-auto">
                    <button
                        className="flex items-center px-2 py-1 border rounded text-black border-gray-400 cursor-pointer mb-6"
                        onClick={() => setOpenMenu(null)}
                    >
                        <IoMdClose className="text-3xl" />
                    </button>
                    <ul className="flex flex-col gap-4 font-medium">
                        <li className="cursor-pointer hover:text-indigo-700">Home</li>
                        {/* SHOP DROPDOWN */}
                        <li>
                            <details>
                                <summary className="cursor-pointer hover:text-indigo-700">Shop</summary>
                                <ul className="ml-4 mt-2 flex flex-col gap-2">
                                    <li className="hover:text-indigo-700 cursor-pointer">Men</li>
                                    <li className="hover:text-indigo-700 cursor-pointer">Women</li>
                                    <li>
                                        <details>
                                            <summary className="hover:text-indigo-700 cursor-pointer">Accessories</summary>
                                            <ul className="ml-4 mt-1 flex flex-col gap-1">
                                                <li className="hover:text-indigo-700 cursor-pointer">Chargers</li>
                                                <li className="hover:text-indigo-700 cursor-pointer">Cables</li>
                                                <li className="hover:text-indigo-700 cursor-pointer">Headphones</li>
                                            </ul>
                                        </details>
                                    </li>
                                </ul>
                            </details>
                        </li>
                        {/* COLLECTIONS DROPDOWN */}
                        <li>
                            <details>
                                <summary className="cursor-pointer hover:text-indigo-700">Collections</summary>
                                <ul className="ml-4 mt-2 flex flex-col gap-2">
                                    <li className="hover:text-indigo-700 cursor-pointer">Essentials</li>
                                    <li className="hover:text-indigo-700 cursor-pointer">Streetwear</li>
                                    <li className="hover:text-indigo-700 cursor-pointer">Workwear</li>
                                </ul>
                            </details>
                        </li>
                        <li className="cursor-pointer hover:text-indigo-700">LookBook</li>
                        <li className="cursor-pointer hover:text-indigo-700">Contact</li>
                    </ul>
                    <div className="mt-8 flex flex-col gap-4">
                        <input
                            type="text"
                            placeholder="Search..."
                            className="px-3 py-1 rounded-md text-black border border-gray-300 focus:outline-none focus:ring-1 focus:ring-indigo-700" />
                        <button className="px-6 py-3 bg-indigo-700 cursor-pointer rounded-full text-white font-semibold hover:bg-indigo-800 transition duration-300">Create an Account</button>
                    </div>
                </div>
            </nav>
        )}

        <div className="hidden lg:flex items-center gap-4">
            <input
                type="text"
                placeholder="Search..."
                className="px-3 py-1 rounded-md text-black border border-gray-300 focus:outline-none focus:ring-1 focus:ring-indigo-700" />
            <span className="text-xl cursor-pointer" onClick={() => setIsCartOpen(true)}><IoCartOutline className='text-gray-900 hover:text-indigo-700 text-2xl' /></span>
            <button className="px-6 py-3 bg-indigo-700 cursor-pointer rounded-full text-white font-semibold hover:bg-indigo-800 transition duration-300">Create an Account</button>
        </div>
    </header>
    <ShoppingCart isOpen={isCartOpen} onClose={() => setIsCartOpen(false)} />
    </>
)
}

export default Header




In src/component/Hero.jsx, add the code.

import React from 'react'
import hero from "../assets/hero.jpg"; 

const Hero = () => {
return (
    <section className="relative h-[70vh] md:h-[90vh] bg-cover bg-center flex items-center" style={{ backgroundImage: `url(${hero})` }}>
        <div className="absolute inset-0 bg-gray-950 opacity-60 z-0" />
        <div className="relative z-10 px-4 sm:px-8 md:pl-10 max-w-full md:max-w-2xl text-white w-full">
            <p className="uppercase text-base sm:text-lg tracking-widest text-gray-300">Create your own collection</p>
            <h1 className="text-4xl md:text-6xl font-extrabold leading-tight capitalize">
                Elevate Your Style with <span className="text-indigo-700">FabrikFit</span>
            </h1>
            <p className="mt-4 sm:mt-6 text-base sm:text-lg md:text-xl text-indigo-100">
                Discover premium streetwear & fashion-forward collections built for confidence and comfort.
            </p>
            <div className="mt-6 sm:mt-8 flex flex-col sm:flex-row gap-4 justify-center md:justify-start">
                <button className="bg-indigo-700 text-white font-bold px-6 py-3 cursor-pointer rounded-full hover:bg-indigo-800 transition">
                    Shop Now
                </button>
                <button className="border border-white px-6 py-3 rounded-full cursor-pointer hover:bg-white hover:text-indigo-700 hover:font-bold transition">
                    Explore Collections
                </button>
            </div>
        </div>
    </section>
)
}

export default Hero




In src/component/ProductGrid.jsx, add the code.

import { useState } from 'react'
import product1 from "../assets/product-1.webp"
import product2 from "../assets/product-2.webp"
import product3 from "../assets/product-3.webp"
import product4 from "../assets/product-4.webp"
import product5 from "../assets/product-5.webp"
import product6 from "../assets/product-6.webp"
import product7 from "../assets/product-7.webp"
import product8 from "../assets/product-8.webp"
import product9 from "../assets/product-9.webp"
import product10 from "../assets/product-10.webp"
import product11 from "../assets/product-11.webp"
import product12 from "../assets/product-12.webp"
import React from 'react'
import { GoChevronDown } from 'react-icons/go'

const products = [
  {
    name: 'ANNA',
    description: 'Product 1 Sample - Clothing And Accessory Boutiques For Sale',
    originalPrice: '$450.00',
    salePrice: '$418.90',
    image: product1,
    saleTag: 'Sale 7%',
    available: true
  },
  {
    name: 'COLLETTE',
    description: 'Product 2 Sample - Clothing And Accessory Boutiques For Sale',
    salePrice: 'from $48.99',
    image: product2,
    available: true
  },
  {
    name: 'BENJAMIN BUTTON',
    description: 'Product 3 Sample - Clothing And Accessory Boutiques For Sale',
    originalPrice: '$86.00',
    salePrice: 'from $69.99',
    image: product3,
    saleTag: 'Sale 19%',
    available: true
  },
  {
    name: 'TOMORROW',
    description: 'Product 4 Sample - Clothing And Accessory Boutiques For Sale',
    salePrice: '$36.99',
    image: product4,
    available: true
  },
  {
    name: 'Kaftans',
    description: 'Product 5 Sample - Clothing And Accessory Boutiques For Sale',
    salePrice: '$36.99',
    image: product5,
    available: false
  },
  {
    name: 'Boubous',
    description: 'Product 6 Sample - Clothing And Accessory Boutiques For Sale',
    originalPrice: '$450.00',
    salePrice: '$418.90',
    image: product6,
    saleTag: 'Sale 5%',
    available: true
  },
  {
    name: 'Abayas',
    description: 'Product 7 Sample - Clothing And Accessory Boutiques For Sale',
    salePrice: '$418.90',
    image: product7,
    saleTag: 'Sale 17%',
    available: true
  },
  {
    name: 'Sarees',
    description: 'Product 8 Sample - Clothing And Accessory Boutiques For Sale',
    originalPrice: '$450.00',
    salePrice: '$418.90',
    image: product8,
    available: false
  },
  {
    name: 'Tankinis',
    description: 'Product 9 Sample - Clothing And Accessory Boutiques For Sale',
    salePrice: '$418.90',
    image: product9,
    available: false
  },
  {
    name: 'Performance Tops',
    description: 'Product 10 Sample - Clothing And Accessory Boutiques For Sale',
    originalPrice: '$450.00',
    salePrice: '$418.90',
    image: product10,
    saleTag: 'Sale 20%',
    available: true
  },
  {
    name: 'Culottes',
    description: 'Product 11 Sample - Clothing And Accessory Boutiques For Sale',
    originalPrice: '$450.00',
    salePrice: '$418.90',
    image: product11,
    saleTag: 'Sale 20%',
    available: true
  },
  {
    name: 'Blazers',
    description: 'Product 12 Sample - Clothing And Accessory Boutiques For Sale',
    originalPrice: '$450.00',
    salePrice: '$418.90',
    image: product12,
    saleTag: 'Sale 50%',
    available: true
  },
];

const ProductGrid = () => {

  const [visibleCount, setVisibleCount] = useState(4);
  const visibleProducts = products.slice(0, visibleCount);

  const [loadMore, setLoadMore] = useState(false);

  const handleLoadMore = () => {
    setLoadMore(true);
    setTimeout(() => {
        setLoadMore(false);
        setVisibleCount((prev) => prev + 4);
    }, 2000);
  };


  return (
    <div className="px-4 py-10 max-w-7xl mx-auto relative">

        {/* Filter Bar */}
        <div className='relative mb-3 w-fit ml-auto'>
        <select className='appearance-none border border-gray-300 rounded px-4 pr-10 py-2 bg-white text-sm focus:outline-none cursor-pointer' defaultValue={"Featured"}>
            <option value="" disabled>Featured</option>
            <option value="newest">Newest</option>
            <option value="price-low-high">Price: Low to High</option>
            <option value="price-high-low">Price: High to Low</option>
            <option value="best-selling">Best Selling</option>
            <option value="top-rated">Top Rated</option>
            <option value="most-popular">Most Popular</option>  
        </select>
        <GoChevronDown className="w-4 h-4 absolute right-3 top-1/2 transform -translate-y-1/2 text-gray-400 pointer-events-none" />
        </div>
        
       { /* Product Grid */}
      <div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-8">
        {visibleProducts.map((product, index) => (
          <div key={index} className="relative bg-white shadow hover:shadow-lg transition-all duration-300 rounded overflow-hidden group">
            {product.saleTag && (
              <div className="absolute top-0 left-0 bg-red-500 text-white text-xs font-semibold px-2 py-1 z-10">
                {product.saleTag}
              </div>
            )}
            {!product.available && (
              <div className="absolute top-0 left-0 bg-gray-600 text-white text-xs font-semibold px-2 py-1 z-10">
                <span>Sold out</span>
              </div>
            )}
            <div className='overflow-hidden'>
                <img src={product.image} alt={product.name} className="w-full h-[400px] object-cover transition duration-700 group-hover:scale-110" />
            </div>
            <div className="p-4 text-center">
              <h3 className="text-gray-700 font-bold uppercase text-sm">{product.name}</h3>
              <p className="text-sm text-gray-600 mt-1">{product.description}</p>
              <div className="mt-3">
                {product.originalPrice && (
                  <span className="text-gray-400 line-through mr-2">{product.originalPrice}</span>
                )}
                <span className="text-red-500 font-bold">{product.salePrice}</span>
              </div>
            </div>
            <button className="absolute bottom-56 left-1/2 -translate-x-1/2 w-1/2 cursor-pointer bg-gray-800 text-white px-4 py-2 rounded hover:bg-gray-700 transition duration-500 opacity-0 group-hover:opacity-100 group-hover:translate-y-0 translate-y-20">
              {product.available ? 'Add to Cart' : 'Notify Me'}
            </button>
          </div>
        ))}
      </div>

      {visibleCount < products.length ? (
        <div className="mt-10 flex justify-center">
          <button
            onClick={handleLoadMore}
            className="px-20 py-2 bg-transparent text-gray-700 border cursor-pointer uppercase hover:bg-indigo-700 transition duration-300 hover:text-white text-sm"
          >
            {loadMore ? 'Loading...' : 'Load More'}
          </button>
        </div>
      ) : (
        <div className="mt-10 text-center">
          <p className="text-gray-500">No more products to display</p>
        </div>
      )}
    </div>
  )
}

export default ProductGrid




In src/component/ShoppingCart.jsx, add the code.

import React, { useRef, useEffect } from 'react'
import { IoMdClose } from "react-icons/io";

const ShoppingCart = ({ isOpen, onClose }) => {
    const cartRef = useRef();

  useEffect(() => {
    const handleClickOutside = (event) => {
      if (cartRef.current && !cartRef.current.contains(event.target)) {
        onClose();
      }
    };

    if (isOpen) {
      document.addEventListener('mousedown', handleClickOutside);
    }

    return () => {
      document.removeEventListener('mousedown', handleClickOutside);
    };
  }, [isOpen, onClose]);

  return (
     <div
      className={`fixed inset-0 z-50 transition-all duration-300 ${
        isOpen ? 'pointer-events-auto' : 'pointer-events-none'
      }`}
    >
      {/* Backdrop */}
      <div
        className={`absolute inset-0 bg-black transition-opacity duration-300 ${
          isOpen ? 'opacity-40' : 'opacity-0'
        }`}
      />

      {/* Cart Drawer */}
      <div
        ref={cartRef}
        className={`absolute top-0 right-0 h-full w-96 bg-white shadow-lg p-6 transform transition-transform duration-300 ${
          isOpen ? 'translate-x-0' : 'translate-x-full'
        }`}
      >
        <div className='flex justify-between items-center mb-4'>
            <h2 className="text-xl font-bold">Shopping Cart</h2>
            <button onClick={onClose} className='flex items-center px-2 py-1 border rounded text-black border-gray-400 cursor-pointer'><IoMdClose className='text-2xl' /></button>
        </div>
        <p className="text-sm text-gray-500">0 items</p>
        <p className='text-sm text-gray-500 my-4'>Free shipping for all orders over $1000.00!</p>

        <p className='text-sm text-gray-600 text-center'>Your cart is empty</p>
        {/* You can map your cart items here */}
        <button
          className="mt-8 bg-indigo-600 text-white px-4 py-3 w-full rounded hover:bg-indigo-700 uppercase font-semibold cursor-pointer transition"
        >
          Continue Shopping
        </button>
      </div>
    </div>
  )
}

export default ShoppingCart




In App.jsx, add the code.

import React from 'react'
import Header from './components/Header'
import Hero from './components/Hero'
import FilterBar from './components/FilterBar'
import ProductGrid from './components/ProductGrid'
import CollectionSlider from './components/CollectionSlider'  
import Footer from './components/Footer'

const App = () => {
  return <>
    <Header />
    <Hero />
    <FilterBar />
    <ProductGrid />
    <CollectionSlider />
    <Footer />
  </>
}

export default App


Deploy Your App

  1. Initialize Git: git init
  2. Add Project Files: git add .
  3. Commit Changes: git commit -m "Initial commit"
  4. Add your remote GitHub repo: git remote add origin https://github.com/your-username/your-repo-name.git
  5. Push to GitHub: git push -u origin main
  6. Head to netlify.com and add create a new project
  7. Add the new repo as the project and hit Deploy


Conclusion and Final word

Now, we have reached the end of our code, for any information, you can comment any problem or code-not-working issues to resolve it, am always with you. You can also visit my YouTube Channel for more updates on HTML, CSS & JavaScript Designs. I believe you can create "an Ecommerce Website Using React & TailwindCSS". and do so much more with codes. Go extremely far in exploring the world of HTML, CSS, JavaScript React Js & Tailwind Projects, its gonna be fun, trust me 😃.

Keep experimenting! You can add other cool features. Try improving error handling and adding other cool updates to make your chatbot even better.

If you run into any issues, you can download the source code for this AI chatbot project by clicking the “Download” button. Don’t forget to check the README.md file for setup and usage instructions. If you need help, you’ll also find support information there.

Happy Coding Journey 🚀





Post a Comment

0 Comments

Close Menu