74 lines
2.0 KiB
TypeScript
74 lines
2.0 KiB
TypeScript
"use client";
|
|
|
|
import { HTMLAttributes } from "react";
|
|
|
|
interface ProgressBarProps extends HTMLAttributes<HTMLDivElement> {
|
|
value: number;
|
|
max: number;
|
|
variant?: "hp" | "xp" | "default";
|
|
showLabel?: boolean;
|
|
label?: string;
|
|
}
|
|
|
|
const variantClasses = {
|
|
hp: {
|
|
high: "from-green-600 to-green-700",
|
|
medium: "from-yellow-600 to-orange-700",
|
|
low: "from-red-700 to-red-900",
|
|
},
|
|
xp: "from-pixel-gold/80 via-pixel-gold/70 to-pixel-gold/80",
|
|
default: "from-pixel-gold/80 via-pixel-gold/70 to-pixel-gold/80",
|
|
};
|
|
|
|
export default function ProgressBar({
|
|
value,
|
|
max,
|
|
variant = "default",
|
|
showLabel = false,
|
|
label,
|
|
className = "",
|
|
...props
|
|
}: ProgressBarProps) {
|
|
const percentage = Math.min(100, Math.max(0, (value / max) * 100));
|
|
|
|
let gradientClass = "";
|
|
if (variant === "hp") {
|
|
if (percentage > 60) {
|
|
gradientClass = variantClasses.hp.high;
|
|
} else if (percentage > 30) {
|
|
gradientClass = variantClasses.hp.medium;
|
|
} else {
|
|
gradientClass = variantClasses.hp.low;
|
|
}
|
|
} else if (variant === "xp") {
|
|
gradientClass = variantClasses.xp;
|
|
} else {
|
|
gradientClass = variantClasses.default;
|
|
}
|
|
|
|
return (
|
|
<div className={className} {...props}>
|
|
{showLabel && (
|
|
<div className="flex justify-between text-xs text-gray-400 mb-1">
|
|
<span>{label || variant.toUpperCase()}</span>
|
|
<span>
|
|
{value} / {max}
|
|
</span>
|
|
</div>
|
|
)}
|
|
<div className="relative h-2 sm:h-3 bg-gray-900 border border-gray-700 rounded overflow-hidden">
|
|
<div
|
|
className={`absolute inset-0 bg-gradient-to-r ${gradientClass} transition-all duration-1000 ease-out`}
|
|
style={{ width: `${percentage}%` }}
|
|
>
|
|
<div className="absolute inset-0 bg-gradient-to-r from-transparent via-white/10 to-transparent animate-shimmer"></div>
|
|
</div>
|
|
{variant === "hp" && percentage < 30 && (
|
|
<div className="absolute inset-0 border border-red-500 rounded animate-pulse"></div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|