pet_data/app/components/pixel/RetroResourceBar.vue

83 lines
2.9 KiB
Vue
Raw Permalink Normal View History

2025-11-26 06:53:44 +00:00
<template>
2025-11-26 09:53:03 +00:00
<div class="flex flex-col gap-1 w-full">
2025-11-26 06:53:44 +00:00
<div v-if="label" class="flex justify-between items-end px-0.5">
2025-11-26 09:53:03 +00:00
<div class="flex items-center gap-2">
<!-- Pixel Icon -->
<div class="w-4 h-4 flex items-center justify-center">
<slot name="icon"></slot>
</div>
<span class="text-[10px] font-mono font-bold leading-none text-[#8f80a0]">{{ label }}</span>
2025-11-26 06:53:44 +00:00
</div>
2025-11-26 09:53:03 +00:00
<span class="text-[10px] font-mono text-[#e0d8f0] leading-none">{{ Math.floor(current) }}/{{ max }}</span>
2025-11-26 06:53:44 +00:00
</div>
2025-11-26 09:53:03 +00:00
<!-- Segmented Bar Container -->
<div class="h-4 bg-[#1b1026] border-2 border-[#1b1026] relative p-[2px] shadow-[0_0_0_1px_#4a3b5e]">
<!-- Background (Empty segments) -->
<div class="absolute inset-[2px] flex gap-[2px]">
<div v-for="i in segments" :key="`bg-${i}`" class="flex-1 bg-[#2b193f]"></div>
</div>
<!-- Foreground (Filled segments) -->
<div class="absolute inset-[2px] flex gap-[2px] overflow-hidden">
<div
v-for="i in segments"
:key="`fill-${i}`"
class="flex-1 transition-all duration-300 relative"
:class="[
i <= filledSegments ? 'opacity-100' : 'opacity-0',
i === filledSegments + 1 && partialFill > 0 ? 'opacity-100' : ''
]"
>
<!-- The colored block -->
<div
class="w-full h-full relative"
:style="{
backgroundColor: barColor,
width: i === filledSegments + 1 ? `${partialFill}%` : '100%'
}"
>
<!-- Shine/Highlight for 3D effect -->
<div class="absolute top-0 left-0 right-0 h-[40%] bg-white opacity-20"></div>
<div class="absolute bottom-0 left-0 right-0 h-[20%] bg-black opacity-10"></div>
</div>
</div>
2025-11-26 06:53:44 +00:00
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { computed } from 'vue';
interface Props {
current: number;
max: number;
type: 'hp' | 'energy' | 'mana';
label?: string;
2025-11-26 09:53:03 +00:00
segments?: number; // Number of blocks, default 10
2025-11-26 06:53:44 +00:00
}
2025-11-26 09:53:03 +00:00
const props = withDefaults(defineProps<Props>(), {
segments: 10
});
2025-11-26 06:53:44 +00:00
const percentage = computed(() => Math.min(100, Math.max(0, (props.current / props.max) * 100)));
2025-11-26 09:53:03 +00:00
// Calculate how many segments are fully filled
const filledSegments = computed(() => Math.floor((percentage.value / 100) * props.segments));
// Calculate the percentage of the partially filled segment
const partialFill = computed(() => {
const segmentSize = 100 / props.segments;
const remainder = percentage.value % segmentSize;
return (remainder / segmentSize) * 100;
});
2025-11-26 06:53:44 +00:00
const barColor = computed(() => {
2025-11-26 09:53:03 +00:00
if (props.type === 'energy') return '#f6b26b'; // Orange (Star)
if (props.type === 'mana') return '#99e550'; // Green (Potion) - Changed from Cyan
return '#d95763'; // Red (Heart)
2025-11-26 06:53:44 +00:00
});
</script>