Frontend Mentor - E-commerce product page solution

This is a solution to the E-commerce product page challenge on Frontend Mentor. Frontend Mentor challenges help you improve your coding skills by building realistic projects.

Overview

The challenge

Users should be able to:

  • ✔ View the optimal layout for the site depending on their device's screen size
  • ✔ See hover states for all interactive elements on the page
  • ✔ Open a lightbox gallery by clicking on the large product image
  • ✔ Switch the large product image by clicking on the small thumbnail images
  • ✔ Add items to the cart
  • ✔ View the cart and remove items from it

Screenshot

📱 View Smartphone

ecommerce-product-page anteprima

💻 View Desktop

ecommerce-product-page anteprima

🚀 View Desktop Hover

ecommerce-product-page anteprima

🚀 View Lighthouse Performance

ecommerce-product-page anteprima

Links

My process

Built with

  • HTML5
  • Tailwind v4.0.6
  • Mobile-first workflow
  • TypeScript
  • SVGR
  • React
  • React Router
  • Framer Motion
  • Vite
  • JSDoc

What I learned

I learned to create a responsive website using HTML, Tailwind and React, organizing the code into components following the atomic design convention. I learned to separate component logic with custom hooks and TypeScript types. I learned to optimize the application using code splitting and lazy loading, and I also divided the bundle into chunks to improve performance. I learned to use AI (Claude 3.5 Sonnet) to generate project documentation. I learned to use Tailwind CSS v4.0.6, first migrating the project from v3.5.0 with Tailwind's migration tool.

I really like the new Tailwind structure, now I don't have to keep switching between the index.css file and tailwind.config.ts to modify Tailwind variables:

@import url("https://fonts.googleapis.com/css2?family=Kumbh+Sans:wght@400;700&display=swap");
@import "tailwindcss";

@theme {
  --font-kumbh: "Kumbh Sans", sans-serif;

  --color-background: var(--white);
  --color-foreground: var(--very-dark-blue);

  --color-primary: var(--orange);
  --color-primary-foreground: var(--very-dark-blue);
}

@layer base {
  :root {
    --orange: hsl(26, 100%, 55%);
    --very-dark-blue: hsl(220, 13%, 13%);
    --white: hsl(0, 0%, 100%);
  }
}

I learned to use SVGs as React components and change the color with the [&>path]:fill-current class:

<IconCart aria-hidden={true} className="[&>path]:fill-current" />

I started using Framer Motion for animations:

const slideVariants = {
  enter: (direction: number) => ({
    x: direction > 0 ? 1000 : -1000,
    opacity: 0,
  }),
  center: {
    zIndex: 1,
    x: 0,
    opacity: 1,
  },
  exit: (direction: number) => ({
    zIndex: 0,
    x: direction < 0 ? 1000 : -1000,
    opacity: 0,
  }),
};

<AnimatePresence initial={false} custom={direction}>
  <motion.img
    key={currentImage}
    src={imageProducts[currentImage]}
    custom={direction}
    variants={slideVariants}
    initial="enter"
    animate="center"
    exit="exit"
    transition={{
      x: { type: "spring", stiffness: 300, damping: 30 },
      opacity: { duration: 0.2 },
    }}
  />
</AnimatePresence>

Continued development

I really like React Router, but I've watched some videos about TanStack Router and it seems very powerful and more convenient to use, so I plan to explore it in the future.

I've gained some understanding of how Framer Motion works, and besides diving deeper into it, I'm also looking for a new animation library.

It was interesting to see how AI generated comments and documentation for the project. I've decided that in the future, I'll let AI write the documentation, limiting myself to reviewing the comments before committing.

Useful resources

...

Author

Acknowledgments

...