React + MotionLoaders

Breathing dots

Three dots that swell and fade in a slow, coordinated breath, calmer than the usual bounce.

Settings

15px
1.5s

Code

import { motion } from "framer-motion";

interface BreathingDotsProps {
  color?: string;
  size?: number;
  /** Duración de una respiración en segundos. */
  speed?: number;
}

export default function BreathingDots({
  color = "#6e6e73",
  size = 15,
  speed = 1.5,
}: BreathingDotsProps) {
  return (
    <div role="status" aria-label="Loading" className="flex gap-3">
      {[0, 1, 2].map((i) => (
        <motion.span
          key={i}
          className="rounded-full"
          style={{ width: size, height: size, backgroundColor: color }}
          animate={{ scale: [0.72, 1, 0.72], opacity: [0.35, 1, 0.35] }}
          transition={{ duration: speed, delay: i * 0.18, repeat: Infinity }}
        />
      ))}
    </div>
  );
}

Prompt for AI

Paste it into ChatGPT, Claude or Cursor and it will adapt the block to your project with these settings, even if you don’t use React.

More in Loaders

Where to use it

Where bouncing dots feel chatty, these breathing dots feel composed. They suit moments that should stay calm: an AI assistant thinking about an answer, a meditation app preparing a session or a banking app confirming a transfer. The dots grow and brighten one after another, like a slow inhale.

Give them a slower speed than a typical loader, around one and a half to two seconds per cycle, and they become almost soothing. They look lost at tiny sizes, so leave some room around them.