Progress
Show a horizontal bar to indicate task progression.
Usage
Pass an integer as the value
from 0
to 100
to the Progress bar component.
<template>
<UProgress :value="70" />
</template>
Max
You may also set the max
number to set the maximum progress value, which will be relative to 100% percent.
<template>
<UProgress :value="2" :max="5" />
</template>
Steps
You can set an array of named steps in the max
prop to show the active step, at the same time it sets the maximum value.
The first step is always shown at 0%
, making the last 100%
.
<template>
<UProgress
:value="0"
:max="['Waiting to start', 'Cloning...', 'Migrating...', 'Deployed!']"
/>
</template>
Progress indicator
You can add a numeric indicator, which will show the percent on top the progress track.
<template>
<UProgress :value="20" indicator />
</template>
Indeterminate
By not setting a value
, or setting it as null
, the progress bar becomes indeterminate. The bar will be animated as a carousel, but you can change it using the animation
prop for an inverse carousel, a swinging bar or an elastic bar.
<template>
<UProgress animation="carousel" />
</template>
Size
Use the size
prop to change the size of the progress bar.
<template>
<UProgress size="md" :indicator="false" :value="70" />
</template>
Style
Use the color
prop to change the visual style of the Progress bar. The color
can be any color from the ui.colors
object.
<template>
<UProgress color="primary" :indicator="false" :value="70" />
</template>
Slots
indicator
You can use the #indicator
slot to show a custom indicator above the progress bar. It receives the current percent
of progress.
<script setup lang="ts">
const temp = ref(35)
const color = computed(() => {
switch (true) {
case temp.value < 10: return 'blue'
case temp.value < 20: return 'amber'
case temp.value < 30: return 'orange'
default: return 'red'
}
})
</script>
<template>
<UProgress :value="temp" :max="40" :color="color">
<template #indicator="{ percent }">
<div class="text-right" :style="{ width: `${percent}%` }">
<span v-if="temp < 10" class="text-blue-500">Too cold!</span>
<span v-else-if="temp < 20" class="text-amber-500">Warm</span>
<span v-else-if="temp < 30" class="text-orange-500">Hot</span>
<span v-else class="text-red-500 font-bold">🔥 Too hot!</span>
</div>
</template>
</UProgress>
</template>
step-<index>
Use the #step-<index>
to alter the HTML being shown for each step.
<script setup lang="ts">
const task = ref(1)
const steps = [
'Cloning...',
'Migrating...',
'Deploying...'
]
</script>
<template>
<UProgress :value="task" :max="steps" indicator>
<template #step-0="{ step }">
<span class="text-lime-500">
<UIcon name="i-heroicons-arrow-down-circle" /> {{ step }}
</span>
</template>
<template #step-1="{ step }">
<span class="text-amber-500">
<UIcon name="i-heroicons-circle-stack" /> {{ step }}
</span>
</template>
<template #step-2="{ step }">
<span class="text-blue-500">
<UIcon name="i-heroicons-hand-thumb-up" /> {{ step }}
</span>
</template>
</UProgress>
</template>
Props
null
config.default.size
{}
config.default.color
100
config.default.animation
false
Config
{
wrapper: 'w-full flex flex-col gap-2',
indicator: {
container: {
base: 'flex flex-row justify-end',
width: 'min-w-fit',
transition: 'transition-all',
},
align: 'text-end',
width: 'w-fit',
color: 'text-gray-400 dark:text-gray-500',
size: {
'2xs': 'text-xs',
xs: 'text-xs',
sm: 'text-sm',
md: 'text-sm',
lg: 'text-sm',
xl: 'text-base',
'2xl': 'text-base',
},
},
progress: {
base: 'block appearance-none border-none overflow-hidden',
width: 'w-full [&::-webkit-progress-bar]:w-full',
size: {
'2xs': 'h-px',
xs: 'h-0.5',
sm: 'h-1',
md: 'h-2',
lg: 'h-3',
xl: 'h-4',
'2xl': 'h-5',
},
rounded: 'rounded-full [&::-webkit-progress-bar]:rounded-full',
track: '[&::-webkit-progress-bar]:bg-gray-200 [&::-webkit-progress-bar]:dark:bg-gray-700 [@supports(selector(&::-moz-progress-bar))]:bg-gray-200 [@supports(selector(&::-moz-progress-bar))]:dark:bg-gray-700',
bar: '[&::-webkit-progress-value]:rounded-full [&::-webkit-progress-value]:transition-all [&::-webkit-progress-value]:ease-in-out [&::-moz-progress-bar]:rounded-full',
color: 'text-{color}-500 dark:text-{color}-400',
background: '[&::-webkit-progress-value]:bg-current [&::-moz-progress-bar]:bg-current',
indeterminate: {
base: 'indeterminate:relative',
rounded: 'indeterminate:after:rounded-full [&:indeterminate::-webkit-progress-value]:rounded-full [&:indeterminate::-moz-progress-bar]:rounded-full',
},
},
steps: {
base: 'grid grid-cols-1',
color: 'text-{color}-500 dark:text-{color}-400',
size: {
'2xs': 'text-xs',
xs: 'text-xs',
sm: 'text-sm',
md: 'text-sm',
lg: 'text-sm',
xl: 'text-base',
'2xl': 'text-base',
},
},
step: {
base: 'transition-all opacity-0 truncate row-start-1 col-start-1',
align: 'text-end',
active: 'opacity-100',
first: 'text-gray-500 dark:text-gray-400',
},
animation: {
carousel: 'bar-animation-carousel',
'carousel-inverse': 'bar-animation-carousel-inverse',
swing: 'bar-animation-swing',
elastic: 'bar-animation-elastic',
},
default: {
color: 'primary',
size: 'md',
animation: 'carousel',
},
}