diff --git a/@xen-orchestra/lite/src/stories/web-core/ui/progress-bar/ui-progress-bar.story.vue b/@xen-orchestra/lite/src/stories/web-core/ui/progress-bar/ui-progress-bar.story.vue index 561aadabcaa..5aef7ca7173 100644 --- a/@xen-orchestra/lite/src/stories/web-core/ui/progress-bar/ui-progress-bar.story.vue +++ b/@xen-orchestra/lite/src/stories/web-core/ui/progress-bar/ui-progress-bar.story.vue @@ -5,7 +5,7 @@ prop('legend').preset('Legend').required().widget(), prop('value').preset(25).required().widget(), prop('max').num().widget(), - prop('steps').arr('number').help('Meant to display steps values under the progress bar. See Presets.').widget(), + prop('showSteps').bool().help('Meant to display steps values under the progress bar. See Presets.').widget(), ]" :presets > @@ -19,32 +19,23 @@ import { prop } from '@/libs/story/story-param' import UiProgressBar from '@core/components/ui/progress-bar/UiProgressBar.vue' const presets = { - '>= 80': { + 'Warning >= 80%': { props: { legend: 'Ram usage', value: 80, - steps: undefined, }, }, - '>= 90': { + 'Danger >= 90%': { props: { legend: 'Ram usage', value: 95, - steps: undefined, }, }, 'With steps': { props: { legend: 'Ram usage', - value: 50, - steps: [0, 100, 200], - }, - }, - 'With steps >= 80': { - props: { - legend: 'Ram usage', - value: 160, - steps: [0, 100, 200], + value: 250, + max: 200, }, }, } diff --git a/@xen-orchestra/web-core/lib/components/ui/progress-bar/UiProgressBar.vue b/@xen-orchestra/web-core/lib/components/ui/progress-bar/UiProgressBar.vue index a4048434f96..ba3ac6831fe 100644 --- a/@xen-orchestra/web-core/lib/components/ui/progress-bar/UiProgressBar.vue +++ b/@xen-orchestra/web-core/lib/components/ui/progress-bar/UiProgressBar.vue @@ -2,15 +2,14 @@ @@ -19,30 +18,33 @@ import VtsLegendList from '@core/components/legend-list/VtsLegendList.vue' import UiLegend from '@core/components/ui/legend/UiLegend.vue' import { toVariants } from '@core/utils/to-variants.util' +import { useMax } from '@vueuse/math' import { computed } from 'vue' const { - value, + value: _value, max = 100, - steps, + showSteps, } = defineProps<{ legend: string value: number max?: number - steps?: [min: number, half: number, max: number] + showSteps?: boolean }>() -const rawPercentage = computed(() => Math.round((value / max) * 1000) / 10) +const value = useMax(0, () => _value) -const percentage = computed(() => { - if (!steps) { - return rawPercentage.value - } +const isInvalid = computed(() => !Number.isFinite(value.value / max) || value.value <= 0) - const relativeValue = (value / max) * 100 +const percentage = computed(() => (isInvalid.value ? 0 : Math.round((value.value / max) * 100))) - return Math.min(100, Math.round(relativeValue * steps?.[1]) / steps?.[2]) -}) +const maxPercentage = computed(() => (isInvalid.value ? 100 : Math.ceil(percentage.value / 100) * 100)) + +const fillWidth = computed(() => Math.max(0, Math.min((percentage.value / maxPercentage.value) * 100, 100))) + +const shouldShowSteps = computed(() => showSteps || (value.value > max && percentage.value > 0)) + +const steps = computed(() => Math.floor(maxPercentage.value / 100)) const accent = computed(() => { if (percentage.value >= 90) { @@ -72,7 +74,8 @@ const accentClass = computed(() => toVariants({ accent: accent.value })) overflow: hidden; background-color: var(--color-neutral-background-disabled); - .segment { + .fill { + width: 0; height: 100%; transition: width 0.25s ease-in-out; } @@ -91,19 +94,19 @@ const accentClass = computed(() => toVariants({ accent: accent.value })) /* ACCENT */ &.accent--info { - .segment { + .fill { background-color: var(--color-info-item-base); } } &.accent--warning { - .segment { + .fill { background-color: var(--color-warning-item-base); } } &.accent--danger { - .segment { + .fill { background-color: var(--color-danger-item-base); } }