caliper uidocs

Progress

Free

A measured bar for work with a known size, such as an upload.

Installs components/ui/progress.tsxDepends on lucide-reactMotion shared motion tokens
pnpm dlx shadcn@latest add https://caliperui.site/r/progress.json

Uploading report

20%

When to use #

Use it for

  • You know how much is done and how much remains.
  • Uploads, imports and multi-step processing.

Skip it when

  • The total is unknown; use a loader.
  • The structure of incoming content is known; use a skeleton.

Installation #

terminal
pnpm dlx shadcn@latest add https://caliperui.site/r/progress.json

Adds its 3 files to components/ui/, each with its own stylesheet, and installs their packages. No account needed. The first part also adds Caliper UI’s tokens; import them once as in Installation.

Usage #

This is the code behind the preview above.

example.tsx
import { useState } from "react"
import { Button } from "@/components/ui/button"
import { Progress } from "@/components/ui/progress"

export function UploadProgress() {
  const [sent, setSent] = useState(24);
  return (
    <div className="grid w-full max-w-sm gap-3">
      <Progress label="Uploading report" value={sent} max={120} showValue />
      <div className="flex gap-2">
        <Button size="sm" variant="secondary" onClick={() => setSent((value) => Math.min(120, value + 24))}>Advance</Button>
        <Button size="sm" variant="ghost" onClick={() => setSent(0)}>Reset</Button>
      </div>
    </div>
  );
}

API reference #

Progress

component

Also accepts the native props of its root element and a ref.

PropTypeDefault
valuenumber0
maxnumber100
labelstring—
showValuebooleanfalse

Accessibility #

It exposes progressbar semantics, with aria-hidden, aria-valuemin, aria-valuemax, aria-valuenow, aria-valuetext and aria-label kept in step with state.

No custom key handling; Tab and the native activation keys do the work.

Motion #

Transitions use the shared duration and easing tokens. Under prefers-reduced-motion those tokens collapse to instant and travel distances go to zero, so state changes still happen without movement.