🔥 Oxide UI v0.1.0 — Dark mode only, copy-paste ready. Get started →
Skip to content

Progress

<div role="progressbar">

Visual indicator of completion or usage. Use for file uploads, API quota, build steps, or any measurable operation.

Overview

Preview
Uploading thumbnails.zip40%
API quota8,540 / 10,000
Storage used23%
Processing...
Build progress
40%

Basic progress bar

Preview
Uploading65%
html
<div class="space-y-1.5">
  <div class="flex justify-between text-xs">
    <span class="text-zinc-400">Uploading</span>
    <span class="tabular-nums text-zinc-500">65%</span>
  </div>
  <div
    role="progressbar"
    aria-valuenow="65"
    aria-valuemin="0"
    aria-valuemax="100"
    class="h-1.5 w-full overflow-hidden rounded-full bg-zinc-800"
  >
    <div
      class="h-full rounded-full bg-gradient-to-r from-[#D40C37] to-[#e8103f] transition-all duration-300"
      style="width: 65%"
    ></div>
  </div>
</div>

Colour variants

Preview
html
<!-- Brand / danger (>80%) -->
<div class="h-full rounded-full bg-gradient-to-r from-[#D40C37] to-[#e8103f]" style="width: 85%"></div>

<!-- Warning (50–80%) -->
<div class="h-full rounded-full bg-amber-500" style="width: 60%"></div>

<!-- Success / healthy (<50%) -->
<div class="h-full rounded-full bg-emerald-500" style="width: 30%"></div>

Sizes

html
<div class="h-1   w-full overflow-hidden rounded-full bg-zinc-800"><div class="h-full rounded-full bg-[#D40C37]" style="width:65%"></div></div>
<div class="h-1.5 w-full overflow-hidden rounded-full bg-zinc-800"><div class="h-full rounded-full bg-[#D40C37]" style="width:65%"></div></div>
<div class="h-2   w-full overflow-hidden rounded-full bg-zinc-800"><div class="h-full rounded-full bg-[#D40C37]" style="width:65%"></div></div>
<div class="h-3   w-full overflow-hidden rounded-full bg-zinc-800"><div class="h-full rounded-full bg-[#D40C37]" style="width:65%"></div></div>

Thick bar with label inside

Preview
72%
html
<div class="h-5 w-full overflow-hidden rounded-full bg-zinc-800 relative">
  <div class="h-full rounded-full bg-[#D40C37]/80 flex items-center justify-end pr-2" style="width: 72%">
    <span class="text-[9px] font-bold text-white tabular-nums">72%</span>
  </div>
</div>

Indeterminate / animated

Preview
html
<div class="h-1.5 w-full overflow-hidden rounded-full bg-zinc-800 relative">
  <div class="absolute h-full w-1/2 rounded-full bg-[#D40C37] animate-[indeterminate_1.5s_ease-in-out_infinite]"></div>
</div>

Add to tailwind.config.js:

js
theme: {
  extend: {
    keyframes: {
      indeterminate: {
        '0%':   { transform: 'translateX(-100%)' },
        '100%': { transform: 'translateX(300%)' },
      },
    },
  },
},

With Vue reactivity

vue
<script setup>
import { ref } from 'vue'
const progress = ref(0)

// Simulate upload
function startUpload() {
  const interval = setInterval(() => {
    progress.value = Math.min(100, progress.value + 5)
    if (progress.value >= 100) clearInterval(interval)
  }, 200)
}
</script>

<template>
  <div>
    <div class="h-1.5 w-full overflow-hidden rounded-full bg-zinc-800">
      <div
        class="h-full rounded-full bg-[#D40C37] transition-all duration-300"
        :style="{ width: progress + '%' }"
        role="progressbar"
        :aria-valuenow="progress"
        aria-valuemin="0"
        aria-valuemax="100"
      ></div>
    </div>
    <button @click="startUpload" class="mt-3 ...">Start upload</button>
  </div>
</template>

Accessibility notes

  • Use role="progressbar" with aria-valuenow, aria-valuemin, aria-valuemax
  • For indeterminate bars, omit aria-valuenow and add aria-label="Loading"
  • If the progress label is not visible, add aria-label to the progressbar element

Released under the MIT License.