72%
React + MotionLoaders

Progress ring

A round progress indicator with the percentage in the middle that springs smoothly to each new value.

Settings

72%
112px

Code

import { motion } from "framer-motion";

const RADIUS = 42;
const CIRCUMFERENCE = 2 * Math.PI * RADIUS;

interface WatchProgressRingProps {
  color?: string;
  /** Progreso de 0 a 100. */
  progress?: number;
  size?: number;
}

export default function WatchProgressRing({
  color = "#0071e3",
  progress = 72,
  size = 112,
}: WatchProgressRingProps) {
  return (
    <div
      role="progressbar"
      aria-valuenow={progress}
      aria-valuemin={0}
      aria-valuemax={100}
      className="relative grid place-items-center text-[#1d1d1f] dark:text-[#f5f5f7]"
      style={{ width: size, height: size }}
    >
      <svg viewBox="0 0 100 100" className="absolute inset-0 -rotate-90">
        <circle
          cx="50"
          cy="50"
          r={RADIUS}
          fill="none"
          strokeWidth="9"
          className="stroke-black/5 dark:stroke-white/10"
        />
        <motion.circle
          cx="50"
          cy="50"
          r={RADIUS}
          fill="none"
          stroke={color}
          strokeWidth="9"
          strokeLinecap="round"
          strokeDasharray={CIRCUMFERENCE}
          animate={{ strokeDashoffset: CIRCUMFERENCE * (1 - progress / 100) }}
          transition={{ type: "spring", stiffness: 300, damping: 30 }}
        />
      </svg>
      <motion.strong
        key={progress}
        initial={{ scale: 0.8, opacity: 0 }}
        animate={{ scale: 1, opacity: 1 }}
        className="text-xl"
      >
        {progress}%
      </motion.strong>
    </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

A circular progress bar is ideal when the number itself matters: how complete a user profile is, how much of a course a student has finished or how close someone is to today’s step goal in a fitness app. The ring springs to each new value, much like the activity rings on a smartwatch.

Only use it when you know the real percentage, because a ring that jumps backwards loses people’s trust. One ring per card is enough. Pick a color with good contrast against the grey track, especially on light backgrounds.