Introducing MotionX Pro - 30+ blocks and templates to build beautiful landing pages in minutes.

Command Palette

Search for a command to run...

Docs
Progress Circle

Progress Circle

A customizable circular progress indicator with smooth animations and accessibility features

75%
Complete

Installation

Usage

import { ProgressCircle } from "@/components/ui/circular-progress";
 
const CircularProgressDemo = () => {
  return (
    <ProgressCircle
      percent={75}
      size={120}
      stroke={8}
      progressClass="stroke-blue-500"
      duration={2}
    >
      <div className="text-center">
        <div className="text-2xl font-bold">75%</div>
        <div className="text-xs text-muted-foreground">Complete</div>
      </div>
    </ProgressCircle>
  );
};
 
export default CircularProgressDemo;

Examples

Custom Colors

<ProgressCircle
  percent={85}
  size={120}
  stroke={8}
  progressClass="stroke-emerald-500"
  trackClass="stroke-emerald-100"
>
  <div className="text-center">
    <div className="text-xl font-bold text-emerald-600">85%</div>
    <div className="text-xs text-muted-foreground">Success Rate</div>
  </div>
</ProgressCircle>

Multiple Sizes

<div className="flex items-end gap-6">
  <ProgressCircle percent={75} size={80} stroke={6}>
    <span className="text-sm font-medium">75%</span>
  </ProgressCircle>
 
  <ProgressCircle percent={75} size={120} stroke={8}>
    <span className="text-xl font-bold">75%</span>
  </ProgressCircle>
 
  <ProgressCircle percent={75} size={160} stroke={10}>
    <div className="text-center">
      <div className="text-2xl font-bold">75%</div>
      <div className="text-sm text-muted-foreground">Complete</div>
    </div>
  </ProgressCircle>
</div>

Skills Dashboard

function SkillsDashboard() {
  const skills = [
    { name: "React", level: 90, color: "stroke-blue-500" },
    { name: "TypeScript", level: 85, color: "stroke-cyan-500" },
    { name: "Node.js", level: 80, color: "stroke-green-500" },
    { name: "Design", level: 75, color: "stroke-purple-500" },
  ];
 
  return (
    <div className="grid grid-cols-2 md:grid-cols-4 gap-6">
      {skills.map((skill, index) => (
        <div key={skill.name} className="text-center">
          <ProgressCircle
            percent={skill.level}
            size={100}
            stroke={6}
            progressClass={skill.color}
            duration={1.5 + index * 0.2}
          >
            <div className="text-center">
              <div className="text-lg font-bold">{skill.level}%</div>
            </div>
          </ProgressCircle>
          <h3 className="mt-3 font-medium text-sm">{skill.name}</h3>
        </div>
      ))}
    </div>
  );
}

Loading State

import { useState, useEffect } from "react";
 
function LoadingExample() {
  const [progress, setProgress] = useState(0);
 
  useEffect(() => {
    const timer = setInterval(() => {
      setProgress((prev) => {
        if (prev >= 100) {
          clearInterval(timer);
          return 100;
        }
        return prev + 1;
      });
    }, 50);
 
    return () => clearInterval(timer);
  }, []);
 
  return (
    <ProgressCircle
      percent={progress}
      size={140}
      stroke={10}
      progressClass="stroke-blue-500"
      duration={0.1}
    >
      <div className="text-center">
        <div className="text-2xl font-bold">{progress}%</div>
        <div className="text-sm text-muted-foreground">
          {progress < 100 ? "Loading..." : "Complete!"}
        </div>
      </div>
    </ProgressCircle>
  );
}

Props

PropTypeDefaultDescription
percentnumberRequiredProgress percentage (0-100)
sizenumber120Circle diameter in pixels
strokenumber8Stroke width in pixels
trackClassstring"stroke-muted"CSS class for background track
progressClassstring"stroke-primary"CSS class for progress arc
childrenReact.ReactNodeundefinedContent to display in center
classNamestring""Additional CSS classes for container
durationnumber1.5Animation duration in seconds