Scrolling Social Proof

An infinite scrolling component for displaying logos and other components

TRUSTED BY LEADING COMPANIES

Google logo
Microsoft logo
Apple logo
Amazon logo
Meta logo
Netflix logo
NVIDIA logo
OpenAI logo
Google logo
Microsoft logo
Apple logo
Amazon logo
Meta logo
Netflix logo
NVIDIA logo
OpenAI logo
Google logo
Microsoft logo
Apple logo
Amazon logo
Meta logo
Netflix logo
NVIDIA logo
OpenAI logo
Google logo
Microsoft logo
Apple logo
Amazon logo
Meta logo
Netflix logo
NVIDIA logo
OpenAI logo

Installation

1

Install dependencies

npm install framer-motion tailwind-merge clsx
2

Add util file

lib/utils.ts

import { ClassValue, clsx } from "clsx";
import { twMerge } from "tailwind-merge";

export function cn(...inputs: ClassValue[]) {
  return twMerge(clsx(inputs));
}
3

Add the following code in the tailwind.config.js file

import type { Config } from "tailwindcss";

export default {
  darkMode: ["class"],
  content: [
    "./pages/**/*.{js,ts,jsx,tsx,mdx}",
    "./components/**/*.{js,ts,jsx,tsx,mdx}",
    "./app/**/*.{js,ts,jsx,tsx,mdx}",
  ],
  theme: {
    extend: {
      animation: {
        socialproof: "socialproof var(--duration) linear infinite",
      },
      keyframes: {
        socialproof: {
          from: { transform: "translateX(0)" },
          to: { transform: "translateX(calc(-100% - var(--gap)))" },
        },
      },
      // other code
    }
  },
  plugins: [require("tailwindcss-animate")],
} satisfies Config;
4

Copy the source code

components/ui/social-proof.tsx
import React from 'react';
import { cn } from "@/lib/utils";

interface ScrollingSocialProofProps extends React.HTMLAttributes<HTMLDivElement> {
  className?: string;
  reverse?: boolean;
  children?: React.ReactNode;
  repeat?: number;
}

export function ScrollingSocialProof({
  className,
  reverse,
  children,
  repeat = 4,
  ...props
}: ScrollingSocialProofProps) {
  return (
    <div className="relative">
      <div className="absolute left-0 top-0 h-full w-[10%] bg-gradient-to-r from-white via-white/80 dark:from-black dark:to-black/5 to-transparent z-10" />
      <div className="absolute right-0 top-0 h-full w-[10%] bg-gradient-to-l from-white via-white/80 dark:from-black dark:to-black/5 to-transparent z-10" />
      <div
        {...props}
        className={cn(
          "group flex flex-row overflow-hidden p-2 [--duration:40s] [--gap:1rem] [gap:var(--gap)]",
          className,
        )}
      >
        {Array(repeat)
          .fill(0)
          .map((_, i) => (
            <div
              key={i}
              className={cn("flex shrink-0 justify-around [gap:var(--gap)] animate-socialproof flex-row", {
                "[animation-direction:reverse]": reverse,
              })}
            >
              {children}
            </div>
          ))}
      </div>
    </div>
  );
}

Props

PropTypeDescriptionDefault Value
classNamestringClass names for the componentundefined
reversebooleanReverse direction of scrollundefined
childrenReactNodeThe images or elements that will be scrolled with the componentundefined
repeatnumberNumber of times to repeat the string of images or elements for more seamless scrolling4