UM
Urooj Murtaza

Testimonials Section - Copy this React, Tailwind Component to your project

import { Avatar } from "antd"; import { useState, useEffect, useCallback } from "react"; // import { BsChevronLeft, BsChevronRight } from "react-icons/bs"; const TestimonialsSection = () => { const testimonials = [ { id: 1, name: "Sarah Johnson", designation: "Marketing Director", profileImage: "https://images.unsplash.com/photo-1494790108377-be9c29b29330", reviewText: "Working with this team has been an absolute game-changer for our business. Their attention to detail and innovative solutions have helped us achieve remarkable results." }, { id: 2, name: "Michael Chen", designation: "Tech Lead", profileImage: "https://images.unsplash.com/photo-1472099645785-5658abf4ff4e", reviewText: "The level of professionalism and expertise demonstrated by the team is outstanding. They've consistently delivered beyond our expectations." }, { id: 3, name: "Emily Rodriguez", designation: "Product Manager", profileImage: "https://images.unsplash.com/photo-1438761681033-6461ffad8d80", reviewText: "I've never worked with a more dedicated and talented group of professionals. Their commitment to excellence is truly remarkable." } ]; const [currentIndex, setCurrentIndex] = useState(0); const [isAutoPlaying, setIsAutoPlaying] = useState(true); const nextTestimonial = useCallback(() => { setCurrentIndex((prevIndex) => prevIndex === testimonials.length - 1 ? 0 : prevIndex + 1 ); }, [testimonials.length]); const prevTestimonial = () => { setCurrentIndex((prevIndex) => prevIndex === 0 ? testimonials.length - 1 : prevIndex - 1 ); }; useEffect(() => { let interval; if (isAutoPlaying) { interval = setInterval(nextTestimonial, 5000); } return () => clearInterval(interval); }, [isAutoPlaying, nextTestimonial]); const handleMouseEnter = () => setIsAutoPlaying(false); const handleMouseLeave = () => setIsAutoPlaying(true); return ( <section className="py-16 px-4 md:px-8 lg:px-16 bg-gradient-to-br from-gray-50 to-gray-100"> <div className="max-w-7xl mx-auto grid md:grid-cols-2 gap-12 items-center"> <div className="space-y-6"> <p className="text-sm font-semibold tracking-wider text-blue-600">TESTIMONIALS</p> <h2 className="text-4xl md:text-5xl font-bold text-gray-900 leading-tight"> What People Say About Us </h2> <div className="flex space-x-3 mt-8"> {testimonials.map((_, index) => ( <button key={index} onClick={() => setCurrentIndex(index)} className={`w-3 h-3 rounded-full transition-all duration-300 ${index === currentIndex ? "bg-blue-600 w-6" : "bg-gray-300 hover:bg-blue-400"}`} aria-label={`Go to testimonial ${index + 1}`} /> ))} </div> </div> <div className="relative" onMouseEnter={handleMouseEnter} onMouseLeave={handleMouseLeave} > <div className="absolute top-4 left-4 w-full h-full bg-blue-100 rounded-2xl transform -rotate-3 opacity-20" /> <div className="relative bg-white rounded-2xl p-8 shadow-xl"> {/* <div className="flex flex-col items-center text-center"> <div className="relative w-20 h-20 mb-6"> <img src={testimonials[currentIndex].profileImage} alt={testimonials[currentIndex].name} className="w-full h-full object-cover rounded-full" onError={(e) => { e.target.src = "https://images.unsplash.com/photo-1535713875002-d1d0cf377fde"; }} /> </div> <p className="text-gray-700 italic text-lg mb-6"> "{testimonials[currentIndex].reviewText}" </p> <h4 className="font-bold text-gray-900 text-xl"> {testimonials[currentIndex].name} </h4> <p className="text-gray-600 text-sm"> {testimonials[currentIndex].designation} </p> </div> */} <div className="mb-10 relative sm:w-[26rem] "> {/* White Box (Top Layer) */} <div className="bg-white sm:w-[26rem] w-[18rem] min-h-[13rem] p-6 z-10 relative shadow-[0px_27.15px_77.72px_0px_rgba(191,191,191,0.25)] rounded-lg"> <div className="absolute -top-10 -left-[61px] "> <Avatar src={testimonials[currentIndex]?.profileImage} size={60} /> </div> <p className="leading-5"> "{testimonials[currentIndex].reviewText}" </p> <p className="text-[#333] font-semibold mt-4"> Salim Ahmed </p> <p className="text-[#666] text-sm">UI Designer</p> </div> {/* Background Box (Bottom Layer) */} <div className="absolute top-12 left-10 sm:w-[26rem] w-[17rem] sm:min-h-[14rem] h-[15.5rem] sm:h-full border-[0.57px] border-[#928282] z-0 rounded-lg flex flex-col justify-end px-2 py-3"> <p className="text-[#333] font-semibold">Salim Ahmed</p> <p className="text-[#666] text-sm">UI Designer</p> </div> </div> <div className="absolute top-1/2 -translate-y-1/2 flex justify-between w-full left-0 px-4"> <button onClick={prevTestimonial} className="p-2 rounded-full bg-white shadow-lg hover:bg-gray-50 transition-all" aria-label="Previous testimonial" > {/* <BsChevronLeft className="w-5 h-5 text-gray-600" /> */} ? </button> <button onClick={nextTestimonial} className="p-2 rounded-full bg-white shadow-lg hover:bg-gray-50 transition-all" aria-label="Next testimonial" > {/* <BsChevronRight className="w-5 h-5 text-gray-600" /> */} ! </button> </div> </div> </div> </div> </section> ); }; export default TestimonialsSection;

Prompt

About

TestimonialsSection - Showcases a "TESTIMONIALS" header, a bold title, and carousel indicators. Features profile pics, speech bubble rev. Access free code!

Share

Last updated 1 month ago