Display a non-modal dialog that floats around a trigger element.
Pass an integer as the value
from 0
to 100
to the Progress bar component.
<template>
<UProgress :value="70" />
</template>
Check out the Range component for forms.
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>
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>
You can add a numeric indicator, which will show the percent on top the progress track.
<template>
<UProgress :value="20" indicator />
</template>
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>
Use the size
prop to change the size of the progress bar.
<template>
<UProgress size="md" :indicator="false" :value="70" />
</template>
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>
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>
size
"md" | "2xs" | "xs" | "sm" | "lg" | "xl" | "2xl"
config.default.size
value
number
null
color
string
config.default.color
max
number | any[]
100
ui
{}
animation
"carousel" | "carousel-inverse" | "swing" | "elastic"
config.default.animation
indicator
boolean
false
{
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'
}
}