68 lines
2.0 KiB
TypeScript
68 lines
2.0 KiB
TypeScript
interface ProgressBarProps {
|
|
percentages: number[];
|
|
colors?: string[];
|
|
textColors?: string[];
|
|
displayPercentage?: boolean;
|
|
}
|
|
|
|
export default function ProgressBar({
|
|
percentages,
|
|
colors,
|
|
textColors,
|
|
displayPercentage = true,
|
|
}: ProgressBarProps) {
|
|
if (!colors) {
|
|
colors = ["bg-green-300", "bg-yellow-400", "bg-orange-500", "bg-red-600"];
|
|
}
|
|
if (!textColors) {
|
|
textColors = ["text-black", "text-black", "text-white", "text-white"];
|
|
}
|
|
const getColor = (index: number) => {
|
|
return colors ? colors[index] || "bg-neutral-100" : "bg-neutral-100";
|
|
};
|
|
const getTextColor = (index: number) => textColors?.[index] || "text-black";
|
|
|
|
const sortedPercentages = [...percentages].sort((a, b) => b - a);
|
|
return (
|
|
<div className="relative">
|
|
<div
|
|
className={`absolute top-0 left-0 h-4 bg-neutral-50 border-2 border-neutral-100`}
|
|
style={{ width: `100%` }}
|
|
></div>
|
|
{sortedPercentages.map((percentage, index) => {
|
|
const spanleft =
|
|
100 -
|
|
(((percentage - sortedPercentages[index + 1]) / 2) * 100) /
|
|
percentage;
|
|
|
|
return (
|
|
<div
|
|
key={index}
|
|
className={`absolute top-0 left-0 h-4 ${getColor(index)} group`}
|
|
style={{ width: `${percentage}%` }}
|
|
>
|
|
{displayPercentage &&
|
|
percentage > 0 &&
|
|
(spanleft < 96 || isNaN(spanleft)) && (
|
|
<span
|
|
className={`absolute opacity-0 group-hover:opacity-100 transition-opacity duration-300 px-1 text-xs ${getTextColor(
|
|
index,
|
|
)}`}
|
|
style={{
|
|
left: `${
|
|
index === sortedPercentages.length - 1 ? 50 : spanleft
|
|
}%`,
|
|
transform: "translateX(-50%)",
|
|
whiteSpace: "nowrap",
|
|
}}
|
|
>
|
|
{percentage}%
|
|
</span>
|
|
)}
|
|
</div>
|
|
);
|
|
})}
|
|
</div>
|
|
);
|
|
}
|