Loaders
MorphSpinner
One shape turns while it melts from square to circle to leaf and back, shifting colour.
Download
- React
- Tailwind CSS v4
- motion
components/ui/morph-spinner.tsx
"use client";
import { motion, useReducedMotion } from "motion/react";
type MorphSpinnerProps = {
className?: string;
color?: string;
/** Second colour the shape blends into. */
accent?: string;
/** Loader width in pixels. */
size?: number;
/** 1 is the default pace; 2 is twice as fast. */
speed?: number;
/** Read out by screen readers. */
label?: string;
};
/* MorphSpinner: one shape turns while it melts from square to circle to leaf and back, shifting colour. */
export function MorphSpinner({
className = "",
color = "#a78bfa",
accent = "#f472b6",
size = 56,
speed = 1,
label = "Loading",
}: MorphSpinnerProps) {
const reduce = useReducedMotion();
return (
<div role="status" className={`inline-grid place-items-center ${className}`} style={{ width: size, height: size }}>
<span className="sr-only">{label}</span>
<motion.span
aria-hidden
className="block"
style={{ width: size * 0.7, height: size * 0.7 }}
animate={
reduce
? { backgroundColor: [color, accent, color] }
: {
rotate: [0, 90, 180, 270, 360],
borderRadius: ["18%", "50%", "50% 0%", "50%", "18%"],
backgroundColor: [color, accent, color, accent, color],
scale: [1, 0.85, 1, 0.85, 1],
}
}
transition={{ duration: (reduce ? 4 : 2.4) / speed, repeat: Infinity, ease: "easeInOut" }}
/>
</div>
);
}
1. Install the dependency.
npm i motion2. Paste the Code tab into
components/ui/morph-spinner.tsx. The styles are Tailwind CSS v4 classes.3. Use it. This is the preview above:
app/morph-spinner-demo.tsx
import { MorphSpinner } from "@/components/ui/morph-spinner"; export default function MorphSpinnerExample() { return ( <div className="grid h-full place-items-center bg-[radial-gradient(circle_at_50%_50%,#1d1a33,#0d0c14_70%)]"> <MorphSpinner size={72} /> </div> ); }
Props
| Name | Type | Default | What it does |
|---|---|---|---|
| color | string | "#a78bfa" | Main colour. |
| accent | string | "#f472b6" | Second colour the shape blends into. |
| size | number | 56 | 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. |