Testimonial 10
standard1 ColumnText Align CenterAvatar ImageLogosStar RatingSlider

Code
relume-testimonial10.tsx
"use client";
import { useState, useEffect } from "react";
import React from "react";
import clsx from "clsx";
import {
Carousel,
CarouselContent,
CarouselItem,
CarouselNext,
CarouselPrevious,
type CarouselApi,
} from "@/components/ui/carousel";
import { StarFull } from "relume-icons";
type ImageProps = {
src: string;
alt?: string;
};
type Testimonial = {
numberOfStars: number;
quote: string;
avatar: ImageProps;
name: string;
position: string;
logo: ImageProps;
};
type Props = {
testimonials: Testimonial[];
};
export type Testimonial10Props = React.ComponentPropsWithoutRef<"section"> & Partial<Props>;
export const Testimonial10 = (props: Testimonial10Props) => {
const { testimonials } = {
...Testimonial10Defaults,
...props,
};
const [api, setApi] = useState<CarouselApi>();
const [current, setCurrent] = useState(0);
useEffect(() => {
if (!api) {
return;
}
setCurrent(api.selectedScrollSnap() + 1);
api.on("select", () => {
setCurrent(api.selectedScrollSnap() + 1);
});
}, [api]);
return (
<section className="overflow-hidden px-[5%] py-16 md:py-24 lg:py-28">
<div className="container">
<Carousel
setApi={setApi}
opts={{
loop: true,
align: "start",
}}
className="overflow-hidden"
>
<div className="relative pb-12 md:pb-16 lg:px-8">
<CarouselContent className="ml-0">
{testimonials.map((testimonial, index) => (
<CarouselItem key={index} className="pl-0 md:px-16 lg:px-6">
<TestimonialCard testimonial={testimonial} />
</CarouselItem>
))}
</CarouselContent>
<CarouselPrevious className="hidden md:flex" />
<CarouselNext className="hidden md:flex" />
<div className="absolute right-0 bottom-0 left-0 z-20 flex h-7 justify-center pt-2.5">
{testimonials.map((_, index) => (
<button
key={index}
onClick={() => api?.scrollTo(index)}
className={clsx("relative mx-[3px] inline-block size-2 rounded-full", {
"bg-scheme-text": current === index + 1,
"bg-scheme-text/20": current !== index + 1,
})}
/>
))}
</div>
</div>
</Carousel>
</div>
</section>
);
};
const TestimonialCard = ({ testimonial }: { testimonial: Testimonial }) => {
return (
<div className="mx-auto flex h-full max-w-lg flex-col items-center justify-center text-center">
<div className="mb-6 flex gap-1 md:mb-8">
{Array(testimonial.numberOfStars)
.fill(null)
.map((_, starIndex) => (
<StarFull key={starIndex} className="size-6 text-scheme-text" />
))}
</div>
<h5 className="text-h5 font-bold">{testimonial.quote}</h5>
<div className="mt-6 flex w-full flex-col items-center gap-3 text-center md:mt-8 md:w-auto md:flex-row md:gap-5 md:text-left">
<div className="size-14 min-h-14 min-w-14 overflow-hidden rounded-full">
<img
src={testimonial.avatar.src}
alt={testimonial.avatar.alt}
className="size-full object-cover"
/>
</div>
<div className="mb-4 md:mb-0">
<p className="font-semibold">{testimonial.name}</p>
<p>{testimonial.position}</p>
</div>
<div className="hidden w-px self-stretch bg-scheme-border md:block" />
<div>
<img src={testimonial.logo.src} alt={testimonial.logo.alt} className="max-h-12" />
</div>
</div>
</div>
);
};
const testimonial: Testimonial = {
numberOfStars: 5,
quote:
'"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse varius enim in eros elementum tristique. Duis cursus, mi quis viverra ornare, eros dolor interdum nulla, ut commodo diam libero vitae erat."',
avatar: {
src: "https://d22po4pjz3o32e.cloudfront.net/placeholder-image.svg",
alt: "Testimonial avatar 1",
},
name: "Name Surname",
position: "Position, Company name",
logo: {
src: "https://d22po4pjz3o32e.cloudfront.net/webflow-logo.svg",
alt: "Webflow logo 1",
},
};
export const Testimonial10Defaults: Props = {
testimonials: [testimonial, testimonial],
};npm i @radix-ui/react-slot class-variance-authority@0.7.1 clsx@^2.1.1 embla-carousel-react@^8.5.2 motion@^12.15.0 relume-icons@1.3.0 tailwind-merge@^2.2.2


