Launched best Saas Marketing template at cheap — Check out

Testimonials

Testimonials sections showcase positive feedback and reviews from customers or users. They help build trust and credibility for your product or service, encouraging potential customers to make a purchase or take action.

Testimonials Marquee

Installation

npm install framer-motion lucide-react
pnpm install framer-motion lucide-react
yarn add framer-motion lucide-react
bun add framer-motion lucide-react

Copy and paste the following code into your project.

components/ui/marquee.tsx

marquee.tsx
import { cn } from "@/lib/utils";
import { ComponentPropsWithoutRef } from "react";

interface MarqueeProps extends ComponentPropsWithoutRef<"div"> {
  /**
   * Optional CSS class name to apply custom styles
   */
  className?: string;
  /**
   * Whether to reverse the animation direction
   * @default false
   */
  reverse?: boolean;
  /**
   * Whether to pause the animation on hover
   * @default false
   */
  pauseOnHover?: boolean;
  /**
   * Content to be displayed in the marquee
   */
  children: React.ReactNode;
  /**
   * Whether to animate vertically instead of horizontally
   * @default false
   */
  vertical?: boolean;
  /**
   * Number of times to repeat the content
   * @default 4
   */
  repeat?: number;
}

export function Marquee({
  className,
  reverse = false,
  pauseOnHover = false,
  children,
  vertical = false,
  repeat = 4,
  ...props
}: MarqueeProps) {
  return (
    <div
      {...props}
      className={cn(
        "group flex overflow-hidden p-2 [--duration:40s] [--gap:1rem] [gap:var(--gap)]",
        {
          "flex-row": !vertical,
          "flex-col": vertical,
        },
        className,
      )}
    >
      {Array(repeat)
        .fill(0)
        .map((_, i) => (
          <div
            key={i}
            className={cn("flex shrink-0 justify-around [gap:var(--gap)]", {
              "animate-marquee flex-row": !vertical,
              "animate-marquee-vertical flex-col": vertical,
              "group-hover:[animation-play-state:paused]": pauseOnHover,
              "[animation-direction:reverse]": reverse,
            })}
          >
            {children}
          </div>
        ))}
    </div>
  );
}

Update tailwind.config.ts

/** @type {import('tailwindcss').Config} */
module.exports = {
  theme: {
    extend: {
      animation: {
        marquee: "marquee var(--duration) linear infinite", 
        "marquee-vertical": "marquee-vertical var(--duration) linear infinite", 
      }, 
      keyframes: { 
        marquee: { 
          from: { transform: "translateX(0)" }, 
          to: { transform: "translateX(calc(-100% - var(--gap)))" }, 
        }, 
        "marquee-vertical": { 
          from: { transform: "translateY(0)" }, 
          to: { transform: "translateY(calc(-100% - var(--gap)))" }, 
        }, 
      }, 
    },
  },
};

Props

Highlight Props

PropTypeDefault
children?
React.ReactNode
undefined
className?
string
undefined

TestimonialCard Props

PropTypeDefault
name?
string
undefined
role?
string
undefined
img?
string
undefined
description?
React.ReactNode
undefined
className?
string
undefined