- Gallery
- Dashboard & Analytics
- KPIRing
New
KPIRing
Circular progress ring using SVG with animated stroke, center value, and label
Dashboard & Analyticskpiprogressringcircular
Dependencies
shadcn/ui components needed:
npx shadcn@latest add cardHow to use this component
Copy the code below into your project. Make sure you have the required shadcn/ui dependencies installed. Then import and use the component in your pages or layouts.
Code
1"use client"23import * as React from "react"4import { Card, CardContent } from "@/components/ui/card"5import { cn } from "@/lib/utils"67interface KPIRingProps {8 value: string9 label: string10 percentage: number11 className?: string12}1314export function KPIRing({ value, label, percentage, className }: KPIRingProps) {15 const radius = 7016 const strokeWidth = 817 const circumference = 2 * Math.PI * radius18 const offset = circumference - (percentage / 100) * circumference1920 return (21 <Card className={cn("w-full", className)}>22 <CardContent className="p-6 flex flex-col items-center justify-center">23 <div className="relative">24 <svg width={radius * 2 + strokeWidth} height={radius * 2 + strokeWidth} className="transform -rotate-90">25 <defs>26 <linearGradient id="ringGradient" x1="0%" y1="0%" x2="100%" y2="0%">27 <stop offset="0%" stopColor="rgb(59 130 246)" />28 <stop offset="100%" stopColor="rgb(139 92 246)" />29 </linearGradient>30 </defs>31 <circle32 cx={radius + strokeWidth / 2}33 cy={radius + strokeWidth / 2}34 r={radius}35 fill="none"36 stroke="rgb(226 232 240)"37 strokeWidth={strokeWidth}38 />39 <circle40 cx={radius + strokeWidth / 2}41 cy={radius + strokeWidth / 2}42 r={radius}43 fill="none"44 stroke="url(#ringGradient)"45 strokeWidth={strokeWidth}46 strokeLinecap="round"47 strokeDasharray={circumference}48 strokeDashoffset={offset}49 className="transition-all duration-1000 ease-out animate-pulse"50 style={{ animation: "pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite" }}51 />52 </svg>53 <div className="absolute inset-0 flex flex-col items-center justify-center">54 <span className="text-3xl font-bold tracking-tight">{value}</span>55 <span className="text-sm text-muted-foreground">{label}</span>56 </div>57 </div>58 </CardContent>59 </Card>60 )61}