41 lines
No EOL
1.1 KiB
Vue
41 lines
No EOL
1.1 KiB
Vue
<template>
|
|
<div class="flex items-center gap-2">
|
|
<div class="flex-1 h-3 bg-neutral-200 rounded-full overflow-hidden">
|
|
<div
|
|
class="h-full rounded-full transition-all duration-300"
|
|
:class="barColor"
|
|
:style="{ width: `${Math.min(100, displayPct)}%` }"
|
|
/>
|
|
</div>
|
|
<span class="text-sm font-medium min-w-[3rem] text-right" :class="textColor">
|
|
{{ Math.round(valuePct) }}%
|
|
</span>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
interface Props {
|
|
valuePct: number
|
|
targetPct?: number
|
|
}
|
|
|
|
const props = withDefaults(defineProps<Props>(), {
|
|
targetPct: 100
|
|
})
|
|
|
|
// Display percentage (cap at 200% for visual purposes)
|
|
const displayPct = computed(() => Math.min(200, props.valuePct))
|
|
|
|
// Color based on coverage thresholds
|
|
const barColor = computed(() => {
|
|
if (props.valuePct >= 100) return 'bg-green-500'
|
|
if (props.valuePct >= 80) return 'bg-amber-500'
|
|
return 'bg-red-500'
|
|
})
|
|
|
|
const textColor = computed(() => {
|
|
if (props.valuePct >= 100) return 'text-green-600'
|
|
if (props.valuePct >= 80) return 'text-amber-600'
|
|
return 'text-red-600'
|
|
})
|
|
</script> |