Components

Progress

Determinate bar showing completion of a task from 0 to 100. Built on Radix Progress. Height h-2 (8px), rounded-full, bg-muted track with a bg-primary indicator that slides in from the left.

Updated Jul 17, 2026 by Leonardo Posada

Anatomy

Import 12,340 rows62%
  1. 1
    Progress (root)

    Radix Root. Sets the visual size (h-2 w-full rounded-full) and the muted track surface.

  2. 2
    Indicator

    The filled portion. bg-primary, rounded-full, driven by a translateX(-100 + value)% transform. Animates smoothly on value change.

  3. 3
    Percentage label (external)

    Optional visible number rendered next to the bar. Radix does NOT render one for you — compose it in the parent for accessibility.

Variants

<Progress value={0} />
<Progress value={25} />
<Progress value={50} />
<Progress value={75} />
<Progress value={100} />
Animated (live)

Radix animates value changes via transition-transform out of the box.

Uploading report.csv0%

States

Progress is stateless in shape but visually maps a value 0-100. Empty (0), partial (1-99), and complete (100) all use the same primary indicator. For failed / indeterminate states use Alert, Skeleton or a spinner respectively.

Empty / Partial / Complete
Empty (0%)
Partial (62%)
Complete (100%)
<Progress value={0} />
<Progress value={62} />
<Progress value={100} />
Always pair with a visible label
The bar alone doesn't tell the user what's being measured or how much is left. Always render an external label next to it (e.g. 'Uploading report.csv · 72%'). Radix does not include a built-in text — that's on you.

Recipes

Ready-to-copy compositions covering the most common Yuno usages of this atom.

File upload

Label + filename left, percentage right, Progress bar full-width below. The canonical pattern for uploads (import CSV, avatar, attachments).

report-2026-07.csv72%
<div className="grid gap-2 w-full max-w-md">
  <div className="flex items-center justify-between text-sm">
    <span className="text-foreground inline-flex items-center gap-2">
      <FileArrowUp weight="light" className="size-4 text-muted-foreground" />
      report-2026-07.csv
    </span>
    <span className="text-muted-foreground">72%</span>
  </div>
  <Progress value={72} aria-label="Uploading report-2026-07.csv: 72%" />
</div>
Import job with ETA

Progress bar with a status row below: 'Processing 12,340 of 20,000 rows · ~2 min left'. Use for long-running backend jobs where the user needs reassurance.

Import transactions62%
Processing 12,340 of 20,000 rows · ~2 min left
<div className="grid gap-2 w-full max-w-md">
  <div className="flex items-center justify-between text-sm">
    <span className="text-foreground">Import transactions</span>
    <span className="text-muted-foreground">62%</span>
  </div>
  <Progress value={62} />
  <div className="text-xs text-muted-foreground">
    Processing 12,340 of 20,000 rows · ~2 min left
  </div>
</div>
KPI card meter (quota / allocation)

Progress inside a Card as a quota meter (API usage, rule allocation). Big number on top, label + Progress below, remaining amount right.

API usage
62,340 / 100,000
Resets Jul 3037,660 remaining
<div className="rounded-lg border bg-card p-5 w-full max-w-sm">
  <div className="text-xs text-muted-foreground">API usage</div>
  <div className="mt-1 text-2xl font-semibold text-foreground">
    62,340 <span className="text-sm font-normal text-muted-foreground">/ 100,000</span>
  </div>
  <div className="mt-3 grid gap-2">
    <Progress value={62} aria-label="API usage: 62%" />
    <div className="flex items-center justify-between text-xs text-muted-foreground">
      <span>Resets Jul 30</span>
      <span>37,660 remaining</span>
    </div>
  </div>
</div>
Multi-step wizard header

Progress bar pinned at the top of a wizard-style flow. Value = (currentStep / totalSteps) * 100. Pair with 'Step X of N' text.

Create ruleStep 2 of 4
<div className="grid gap-3 w-full">
  <div className="flex items-center justify-between text-sm">
    <span className="font-medium text-foreground">Create rule</span>
    <span className="text-muted-foreground">Step 2 of 4</span>
  </div>
  <Progress value={50} aria-label="Wizard progress: step 2 of 4" />
  <div className="flex justify-between">
    <Button variant="outline" size="sm">Back</Button>
    <Button size="sm">Continue</Button>
  </div>
</div>

Import

Copy this import line at the top of the file where you compose this atom.

Single-import atom. Compose the label and status text in the parent.
import { Progress } from "@/components/ui/progress";

Props

Everything else from the underlying HTML or Radix primitive is forwarded via ...props.

PropTypeDefaultDescription
valuenumber0Current completion, 0-100. Radix animates the indicator via transition-transform on change.
maxnumber100Upper bound for value. Rarely changed — keeps value as a percentage.
aria-label / aria-labelledbystringRequired for accessibility. Describe what the bar tracks (e.g. 'Uploading report.csv: 72%').
classNamestringMerged onto the root. Default is h-2 w-full rounded-full bg-muted. Do not tint the bar destructive/warning by default.

When to use

  • Uploads, imports, or any measurable operation.
  • Meters inside cards (rule health, allocation, quota).
  • Multi-step wizard headers showing overall progress.
  • Long-running backend jobs where the user is waiting.

When not to use

  • Indeterminate loading — use Skeleton or a spinner.
  • Step-by-step wizards where the current step matters more than the ratio — use Tabs or a stepper.
  • Success / error signaling — use Badge, Alert or Toast.

Usage

Do
  • Always render the percentage as text alongside the bar for accessibility and reassurance.
  • Keep the value between 0 and 100.
  • Animate value changes — Radix does this via transition-transform out of the box.
  • Pair with an aria-label or aria-labelledby that describes what the bar tracks.
Don't
  • Don't tint the bar destructive/warning by default — the bar is neutral.
  • Don't use Progress for indeterminate loading — the bar implies a measurable value.
  • Don't rely on the bar alone — always pair with a visible label.

Related

Cross-links to atoms and patterns you may reach for next.

  • SkeletonFor indeterminate loading (data not ready yet).
  • AlertFor failed / error states after an upload or import.
  • TabsWhen the wizard steps should switch views rather than just show progress.
  • BadgeFor a compact percentage or status label next to the bar.