Skip to content

Instantly share code, notes, and snippets.

@maxotuteye
Forked from eYinka/tailwind-radial-progress-bar.txt
Last active February 5, 2025 13:19
Show Gist options
  • Save maxotuteye/86dc828106847c471a0abbb11a631550 to your computer and use it in GitHub Desktop.
Save maxotuteye/86dc828106847c471a0abbb11a631550 to your computer and use it in GitHub Desktop.
Tailwind CSS Radial Progress Bar
/* This is a react-based fork of tailwind-radial-progress-bar.
* The size is the size of the containing div, given as a tailwind dimension value
* The radius is provided as a prop, and circumference is calculated based on it.
* The strokeDashOffset is dynamically calculated from the circumference.
* The progress is a number as a percentage, such as 50, for 50%.
*/
export const RadialProgressBar = ({size, radius, progress}: { size: number, radius: number, progress: number }) => {
const width = `w-${size}`
const height = `h-${size}`
const circumference = Number((2 * Math.PI * radius).toFixed(1))
const strokeDashOffset = (circumference - (circumference * progress) / 100)
return (
<div className={`relative ${width} ${height}`}>
<svg className="w-full h-full" viewBox="0 0 100 100">
<circle
className="text-gray-200 stroke-current"
strokeWidth="10"
cx="50"
cy="50"
r={radius}
fill="transparent"
/>
<circle
className="text-indigo-500 progress-ring__circle stroke-current"
strokeWidth="10"
strokeLinecap="round"
cx="50"
cy="50"
r={radius}
fill="transparent"
strokeDasharray={circumference}
strokeDashoffset={`${strokeDashOffset}px`}/>
<text
x="50"
y="50"
fontSize="12"
textAnchor="middle"
alignmentBaseline="middle">{progress}%
</text>
</svg>
</div>
)
}
@Omarmarei
Copy link

this worked for me
`// components/CircularProgressBar.tsx
import React from 'react';

interface CircularProgressBarProps {
percentage: number;
size?: number;
strokeWidth?: number;
}

const CircularProgressBar: React.FC = ({
percentage,
size = 120,
strokeWidth = 10,
}) => {
const radius = (size - strokeWidth) / 2;
const circumference = 2 * Math.PI * radius;
const offset = circumference - (percentage / 100) * circumference;

return (
<svg
width={size}
height={size}
viewBox={0 0 ${size} ${size}}
className="circular-progress-bar"
>
<circle
className="circle-bg"
stroke="#e6e6e6"
strokeWidth={strokeWidth}
fill="none"
cx={size / 2}
cy={size / 2}
r={radius}
/>
<circle
className="circle-progress"
stroke="#3b82f6"
strokeWidth={strokeWidth}
strokeLinecap="round"
fill="none"
cx={size / 2}
cy={size / 2}
r={radius}
strokeDasharray={circumference}
strokeDashoffset={offset}
transform={rotate(-90 ${size / 2} ${size / 2})} // Rotate the circle to start at the top
/>

{${percentage}%}


);
};

export default CircularProgressBar;
`

@lumotroph
Copy link

Great work!
I made some improvements / set some defaults over here, take a look if you'd like :)

@firxworx
Copy link

firxworx commented Feb 4, 2025

I saw this and left the same comment on lumotroph's gist. ... Friendly heads up!


Heads up the following is a bad practice for tailwind because the regexes that look for tailwind classes when building the project will fail to recognize this and will not generate CSS for it: const width = w-${size};

The only way this could work in a production build is extremely fragile and based on luck: if you happened to use the exact value e.g. w-4 somewhere else in your code that would be the only reason tailwind would know to generate final production CSS for that class.

If you're wondering why your final build isn't styled right this is your answer.

Use inline style (safest) and/or possibly tailwind arbitrary (square bracket) to define something based on css variables related to the theme.

@lumotroph
Copy link

Thank you @firxworx - response posted on that gist!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment