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>
);
}