forked from Nova-reward/Nova-Rewards
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathProgressCircle.js
More file actions
71 lines (69 loc) · 2.01 KB
/
Copy pathProgressCircle.js
File metadata and controls
71 lines (69 loc) · 2.01 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
/**
* ProgressCircle component with animations and accessibility support
*/
export default function ProgressCircle({
value = 0,
max = 100,
size = 120,
strokeWidth = 8,
label = '',
showPercentage = true,
variant = 'default',
animated = true
}) {
const percentage = Math.min(Math.max((value / max) * 100, 0), 100);
const radius = (size - strokeWidth) / 2;
const circumference = 2 * Math.PI * radius;
const offset = circumference - (percentage / 100) * circumference;
const variantColors = {
default: '#2563eb',
success: '#16a34a',
warning: '#ca8a04',
error: '#dc2626'
};
return (
<div className="inline-flex flex-col items-center">
<div className="relative" style={{ width: size, height: size }}>
<svg
width={size}
height={size}
className={animated ? 'transition-all duration-500' : ''}
role="img"
aria-label={`${label || 'Progress'}: ${Math.round(percentage)}%`}
>
<circle
cx={size / 2}
cy={size / 2}
r={radius}
fill="none"
stroke="#e5e7eb"
strokeWidth={strokeWidth}
/>
<circle
cx={size / 2}
cy={size / 2}
r={radius}
fill="none"
stroke={variantColors[variant]}
strokeWidth={strokeWidth}
strokeDasharray={circumference}
strokeDashoffset={offset}
strokeLinecap="round"
transform={`rotate(-90 ${size / 2} ${size / 2})`}
className={animated ? 'transition-all duration-500 ease-out' : ''}
/>
</svg>
{showPercentage && (
<div className="absolute inset-0 flex items-center justify-center">
<span className="text-lg font-semibold text-gray-700">
{Math.round(percentage)}%
</span>
</div>
)}
</div>
{label && (
<span className="mt-2 text-sm text-gray-600">{label}</span>
)}
</div>
);
}