Loaders
InfinityFlow
A glowing streak runs endlessly along a figure-eight track. Height is half the width.
Download
- React
- Tailwind CSS v4
- motion
components/ui/infinity-flow.tsx
"use client";
import { motion, useReducedMotion } from "motion/react";
type InfinityFlowProps = {
className?: string;
color?: string;
/** Loader width in pixels; height is half of it. */
size?: number;
/** 1 is the default pace; 2 is twice as fast. */
speed?: number;
/** Read out by screen readers. */
label?: string;
};
// Figure-eight in a 100 x 50 box.
const PATH = "M50 25 C62 8 88 8 88 25 C88 42 62 42 50 25 C38 8 12 8 12 25 C12 42 38 42 50 25 Z";
/* InfinityFlow: a glowing streak runs endlessly along a figure-eight track. */
export function InfinityFlow({
className = "",
color = "#a78bfa",
size = 96,
speed = 1,
label = "Loading",
}: InfinityFlowProps) {
const reduce = useReducedMotion();
const flow = { duration: (reduce ? 8 : 2) / speed, repeat: Infinity, ease: "linear" as const };
return (
<div role="status" className={`inline-block ${className}`} style={{ width: size, height: size / 2 }}>
<span className="sr-only">{label}</span>
<svg aria-hidden viewBox="0 0 100 50" className="h-full w-full overflow-visible">
<path d={PATH} fill="none" stroke={color} strokeOpacity={0.15} strokeWidth={5} />
<motion.path
d={PATH}
fill="none"
stroke={color}
strokeWidth={5}
strokeLinecap="round"
pathLength={1}
strokeDasharray="0.28 0.72"
style={{ filter: `drop-shadow(0 0 3px ${color})` }}
initial={{ strokeDashoffset: 0 }}
animate={{ strokeDashoffset: -1 }}
transition={flow}
/>
</svg>
</div>
);
}
1. Install the dependency.
npm i motion2. Paste the Code tab into
components/ui/infinity-flow.tsx. The styles are Tailwind CSS v4 classes.3. Use it. This is the preview above:
app/infinity-flow-demo.tsx
import { InfinityFlow } from "@/components/ui/infinity-flow"; export default function InfinityFlowExample() { return ( <div className="grid h-full place-items-center bg-[radial-gradient(circle_at_50%_50%,#1d1a33,#0d0c14_70%)]"> <InfinityFlow size={140} /> </div> ); }
Props
| Name | Type | Default | What it does |
|---|---|---|---|
| color | string | "#a78bfa" | Main colour. |
| size | number | 96 | Width in pixels. |
| speed | number | 1 | 1 is the default pace; 2 is twice as fast. |
| label | string | "Loading" | Read out by screen readers (role=status). |
| className | string | "" | Extra classes on the wrapper. |