![Jessie J](/_next/image?url=https%3A%2F%2Frandomuser.me%2Fapi%2Fportraits%2Fmen%2F91.jpg&w=128&q=75)
EldoraUI's components make building UIs effortless great work!
Installation
pnpm add @headlessui/react
pnpm add @headlessui/react
Copy and paste the following code into your project.
components/eldoraui/testimonalslider.tsx
"use client";
import { useState, useRef, useEffect } from "react";
import Image from "next/image";
import { Transition } from "@headlessui/react";
interface Testimonial {
img: string;
quote: string;
name: string;
role: string;
}
export function FancyTestimonialsSlider({
testimonials,
}: {
testimonials: Testimonial[];
}) {
const testimonialsRef = useRef<HTMLDivElement>(null);
const [active, setActive] = useState<number>(0);
const [autorotate, setAutorotate] = useState<boolean>(true);
const autorotateTiming: number = 7000;
useEffect(() => {
if (!autorotate) return;
const interval = setInterval(() => {
setActive(
active + 1 === testimonials.length ? 0 : (active) => active + 1,
);
}, autorotateTiming);
return () => clearInterval(interval);
}, [active, autorotate]);
const heightFix = () => {
if (testimonialsRef.current && testimonialsRef.current.parentElement)
testimonialsRef.current.parentElement.style.height = `${testimonialsRef.current.clientHeight}px`;
};
useEffect(() => {
heightFix();
}, []);
return (
<div className="mx-auto w-full max-w-3xl text-center">
{/* Testimonial image */}
<div className="relative h-32">
<div className="pointer-events-none absolute left-1/2 top-0 h-[480px] w-[480px] -translate-x-1/2 before:absolute before:inset-0 before:-z-10 before:rounded-full before:bg-gradient-to-b before:from-fuchsia-500/25 before:via-fuchsia-500/5 before:via-25% before:to-fuchsia-500/0 before:to-75%">
<div className="h-32 [mask-image:_linear-gradient(0deg,transparent,theme(colors.white)_20%,theme(colors.white))]">
{testimonials.map((testimonial, index) => (
<Transition
as="div"
key={index}
show={active === index}
className="absolute inset-0 -z-10 h-full"
enter="transition ease-[cubic-bezier(0.68,-0.3,0.32,1)] duration-700 order-first"
enterFrom="opacity-0 -rotate-[60deg]"
enterTo="opacity-100 rotate-0"
leave="transition ease-[cubic-bezier(0.68,-0.3,0.32,1)] duration-700"
leaveFrom="opacity-100 rotate-0"
leaveTo="opacity-0 rotate-[60deg]"
beforeEnter={() => heightFix()}
>
<Image
className="relative left-1/2 top-11 -translate-x-1/2 rounded-full"
src={testimonial.img}
width={56}
height={56}
alt={testimonial.name}
/>
</Transition>
))}
</div>
</div>
</div>
{/* Text */}
<div className="mb-9 transition-all delay-300 duration-150 ease-in-out">
<div className="relative flex flex-col" ref={testimonialsRef}>
{testimonials.map((testimonial, index) => (
<Transition
key={index}
show={active === index}
enter="transition ease-in-out duration-500 delay-200 order-first"
enterFrom="opacity-0 -translate-x-4"
enterTo="opacity-100 translate-x-0"
leave="transition ease-out duration-300 delay-300 absolute"
leaveFrom="opacity-100 translate-x-0"
leaveTo="opacity-0 translate-x-4"
beforeEnter={() => heightFix()}
>
<div className="text-2xl font-bold text-fuchsia-900 before:content-['\201C'] after:content-['\201D']">
{testimonial.quote}
</div>
</Transition>
))}
</div>
</div>
{/* Buttons */}
<div className="-m-1.5 flex flex-wrap justify-center">
{testimonials.map((testimonial, index) => (
<button
key={index}
className={`m-1.5 inline-flex justify-center whitespace-nowrap rounded-full px-3 py-1.5 text-xs shadow-sm transition-colors duration-150 focus-visible:outline-none focus-visible:ring focus-visible:ring-fuchsia-300 dark:focus-visible:ring-fuchsia-600 ${active === index ? "bg-fuchsia-500 text-white shadow-fuchsia-950/10" : "bg-white text-fuchsia-900 hover:bg-fuchsia-100"}`}
onClick={() => {
setActive(index);
setAutorotate(false);
}}
>
<span>{testimonial.name}</span>{" "}
<span
className={`${active === index ? "text-fuchsia-200" : "text-fuchsia-300"}`}
>
-
</span>{" "}
<span>{testimonial.role}</span>
</button>
))}
</div>
</div>
);
}
Update the import paths to match your project setup.
Props
TestimonialsSlider
Component Props
Prop Name | Type | Default | Description |
---|---|---|---|
testimonials | Testimonial[] | - | Array of testimonial objects containing the image, quote, name, and role. |
Testimonial
Object
Property Name | Type | Description |
---|---|---|
img | string | The URL or path to the image for the testimonial. |
quote | string | The testimonial quote text. |
name | string | The name of the person giving the testimonial. |
role | string | The role of the person giving the testimonial. |