Retour au catalogue

Divider Dot Pattern

Separateur a motif de points repetitifs qui apparaissent en fade-in au scroll. Texture subtile entre sections.

dividersimple Both Responsive a11y
minimalelegantuniversalsaasagencystacked
Theme
"use client";

import { motion, useInView } from "framer-motion";
import { useRef, useMemo } from "react";

interface DividerDotPatternProps {
  rows?: number;
  dotSize?: number;
  gap?: number;
}

export default function DividerDotPattern({
  rows = 3,
  dotSize = 3,
  gap = 16,
}: DividerDotPatternProps) {
  const ref = useRef<HTMLDivElement>(null);
  const inView = useInView(ref, { once: true, margin: "-30px" });

  const cols = useMemo(() => {
    // Estimate columns based on typical container width
    return Math.floor(1200 / (dotSize + gap));
  }, [dotSize, gap]);

  return (
    <motion.div
      ref={ref}
      initial={{ opacity: 0 }}
      animate={inView ? { opacity: 1 } : { opacity: 0 }}
      transition={{ duration: 0.8, ease: [0.16, 1, 0.3, 1] }}
      style={{
        display: "flex",
        justifyContent: "center",
        padding: "1.5rem var(--container-padding-x)",
        background: "var(--color-background)",
        overflow: "hidden",
      }}
    >
      <div
        style={{
          display: "grid",
          gridTemplateColumns: `repeat(${cols}, ${dotSize}px)`,
          gridTemplateRows: `repeat(${rows}, ${dotSize}px)`,
          gap: `${gap}px`,
          maxWidth: "100%",
          overflow: "hidden",
        }}
      >
        {Array.from({ length: rows * cols }).map((_, i) => {
          const row = Math.floor(i / cols);
          const col = i % cols;
          // Center dots more opaque, edges fade
          const distFromCenter = Math.abs(col - cols / 2) / (cols / 2);
          const opacity = Math.max(0.15, 1 - distFromCenter * 1.2);

          return (
            <motion.div
              key={i}
              initial={{ scale: 0 }}
              animate={inView ? { scale: 1 } : { scale: 0 }}
              transition={{
                duration: 0.3,
                delay: (row * 0.05) + (Math.abs(col - cols / 2) * 0.005),
                ease: [0.16, 1, 0.3, 1],
              }}
              style={{
                width: dotSize,
                height: dotSize,
                borderRadius: "var(--radius-full)",
                background: "var(--color-foreground-light)",
                opacity,
              }}
            />
          );
        })}
      </div>
    </motion.div>
  );
}

Avis

Divider Dot Pattern — React Divider Section — Incubator