background-paths.tsx•2.06 kB
"use client";
import { cn } from "@repo/ui/lib/utils";
import { motion } from "framer-motion";
export function FloatingPaths({
position,
color = "text-slate-950 dark:text-white",
}: {
position: number;
color?: string;
}) {
const paths = Array.from({ length: 36 }, (_, i) => ({
id: i,
d: `M-${380 - i * 5 * position} -${189 + i * 6}C-${380 - i * 5 * position
} -${189 + i * 6} -${312 - i * 5 * position} ${216 - i * 6} ${152 - i * 5 * position
} ${343 - i * 6}C${616 - i * 5 * position} ${470 - i * 6} ${684 - i * 5 * position
} ${875 - i * 6} ${684 - i * 5 * position} ${875 - i * 6}`,
color: `rgba(15,23,42,${0.1 + i * 0.03})`,
width: 0.5 + i * 0.03,
}));
return (
<div className="absolute inset-0 pointer-events-none -z-50">
<svg
className={cn("w-full h-full", color)}
viewBox="0 0 696 316"
fill="none"
>
{paths.map((path) => (
<motion.path
key={path.id}
d={path.d}
stroke="currentColor"
strokeWidth={path.width}
strokeOpacity={0.1 + path.id * 0.03}
initial={{ pathLength: 0.3, opacity: 0.6 }}
animate={{
pathLength: 1,
opacity: [0.3, 0.6, 0.3],
pathOffset: [0, 1, 0],
}}
transition={{
duration: 20 + Math.random() * 10,
repeat: Number.POSITIVE_INFINITY,
ease: "linear",
}}
/>
))}
</svg>
</div>
);
}
export default function BackgroundPaths({
title = "Background Paths",
color = "text-slate-950 dark:text-white",
}: {
title?: string;
color?: string;
}) {
const words = title.split(" ");
return (
<div className="relative min-h-screen w-full flex items-center justify-center overflow-hidden bg-white dark:bg-neutral-950">
<div className="absolute inset-0">
<FloatingPaths position={1} color={color} />
<FloatingPaths position={-1} color={color} />
</div>
</div>
);
}