50 行
1.6 KiB
TypeScript
50 行
1.6 KiB
TypeScript
"use client";
|
|
|
|
import { useUiPreferences } from "@/components/ui-preference-provider";
|
|
|
|
type Props = {
|
|
level: number;
|
|
currentXp: number;
|
|
nextLevelXp: number;
|
|
className?: string;
|
|
};
|
|
|
|
export function XpBar({ level, currentXp, nextLevelXp, className = "" }: Props) {
|
|
const { theme } = useUiPreferences();
|
|
const isMc = theme === "minecraft";
|
|
const progress = Math.min(100, Math.max(0, (currentXp / nextLevelXp) * 100));
|
|
|
|
if (!isMc) {
|
|
return null;
|
|
}
|
|
|
|
return (
|
|
<div className={`flex flex-col items-center select-none ${className}`}>
|
|
<div className="relative w-full max-w-[400px]">
|
|
{/* Level Indicator */}
|
|
<div className="absolute -top-3 left-1/2 -translate-x-1/2 text-[#80ff20] drop-shadow-[2px_2px_0_#000] font-[PressStart2P] text-xs z-10">
|
|
{level}
|
|
</div>
|
|
|
|
{/* XP Bar Background */}
|
|
<div className="h-3 w-full bg-[#3a3a3a] border-2 border-black flex relative">
|
|
{/* XP Bar Progress */}
|
|
<div
|
|
className="h-full bg-[#80ff20] transition-all duration-500 ease-out"
|
|
style={{ width: `${progress}%`, boxShadow: "inset 0 2px 0 rgba(255,255,255,0.3), inset 0 -2px 0 rgba(0,0,0,0.2)" }}
|
|
/>
|
|
{/* Segmentation lines (every 10%) */}
|
|
{Array.from({ length: 9 }).map((_, i) => (
|
|
<div key={i} className="absolute top-0 bottom-0 w-[2px] bg-black/20" style={{ left: `${(i + 1) * 10}%` }} />
|
|
))}
|
|
</div>
|
|
</div>
|
|
|
|
{/* XP Text */}
|
|
<div className="mt-1 text-[10px] text-[#80ff20] font-[VT323] drop-shadow-[1px_1px_0_#000]">
|
|
{currentXp} / {nextLevelXp}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|