Docs
Gauge Chart
This graph shows the progress in a donut chart with a gap at bottom.
Installation
Update tailwind.config.js
theme: {
extend: {
colors: {
foreground: "hsl(var(--foreground))",
}
},
},
Run the following command
It will create a new file called gauge-chart.tsx
inside the components/animata/graphs
directory.
mkdir -p components/animata/graphs && touch components/animata/graphs/gauge-chart.tsx
Paste the code
Open the newly created file and paste the following code:
import { ReactNode, useEffect, useState } from "react";
import { cn } from "@/lib/utils";
interface GaugeChartProps {
showValue?: boolean;
size: number;
gap: number;
progress: number;
trackClassName?: string;
progressClassName?: string;
circleWidth?: number;
progressWidth?: number;
rounded?: boolean;
className?: string;
children?: ReactNode;
}
export default function GaugeChart({
showValue,
size,
progress,
gap,
progressClassName = "text-green-500",
trackClassName = "text-black/10 dark:text-white/10",
circleWidth = 16,
progressWidth = 16,
rounded = true,
className,
children,
}: GaugeChartProps) {
const [shouldUseValue, setShouldUseValue] = useState(false);
useEffect(() => {
const timeout = setTimeout(() => {
setShouldUseValue(true);
}, 250);
return () => clearTimeout(timeout);
}, []);
const radius = size / 2 - Math.max(progressWidth, circleWidth);
const circumference = Math.PI * radius * 2;
const adjustedProgress = shouldUseValue ? progress : 0;
// Avoid values less than 0 and greater than 100
const validatedProgress =
adjustedProgress < 0 ? 0 : adjustedProgress > 100 ? 100 : adjustedProgress;
// Calculate the stroke-dashoffset for the progress circle considering the gap
const strokeDashoffsetProgress =
circumference - (validatedProgress / 100) * (circumference - gap);
return (
<div className={className}>
<div className="relative" style={{ width: size }}>
<svg
width={size}
height={size}
viewBox={`0 0 ${size} ${size}`}
version="1.1"
xmlns="http://www.w3.org/2000/svg"
>
{/* Background Circle */}
<circle
r={radius}
cx={size / 2}
cy={size / 2}
fill="transparent"
stroke="currentColor"
strokeWidth={`${circleWidth}px`}
strokeDasharray={circumference}
strokeDashoffset={gap}
strokeLinecap={rounded ? "round" : "butt"}
className={cn("duration-500", trackClassName)}
transform={`rotate(${90 + (gap / (2 * circumference)) * 360} ${size / 2} ${size / 2})`}
/>
{/* Progress Circle */}
<circle
r={radius}
cx={size / 2}
cy={size / 2}
stroke="currentColor"
className={cn("duration-500", progressClassName)}
strokeWidth={`${progressWidth}px`}
strokeLinecap={rounded ? "round" : "butt"}
fill="transparent"
strokeDasharray={circumference}
strokeDashoffset={strokeDashoffsetProgress}
transform={`rotate(${90 + (gap / (2 * circumference)) * 360} ${size / 2} ${size / 2})`}
/>
</svg>
{showValue && (
<div
className="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 font-mono font-bold text-foreground"
style={{ fontSize: size / 4 }}
>
{progress}
</div>
)}
{children}
</div>
</div>
);
}
Credits
Built by Sanjaya Acharya