Skip to content

Progress

  • File uploads and downloads
  • Steps of an import or installation with a known total

Not for a measurement that is not a task — use a Meter — or work of unknown length — use a Spinner.

Choosing between showing progress, loading or a measurement:

ComponentUse it forFor example
ProgressA task whose completion is known, moving toward doneUpload at 40%, step 2 of 5
StepperThe named steps of a multi-step flow, and which one you’re onCheckout: Cart, Shipping, Payment
MeterA measurement within a known range, not a taskDisk usage, password strength, a score
SpinnerWork of unknown length, in a small spaceA button saying “Saving…”, a panel refreshing
SkeletonContent still loading whose shape is known, so the layout does not jumpPlaceholder rows in a list, a profile card
import { useEffect, useState } from 'react';
import { Progress } from '@arun-dev/ui';
const stack = { display: 'grid', gap: 'var(--space-md)', maxInlineSize: '20rem' };
const field = { display: 'grid', gap: 'var(--space-3xs)' };
export default function ProgressBasics() {
const [done, setDone] = useState(20);
useEffect(() => {
const timer = setInterval(() => setDone((d) => (d >= 100 ? 0 : d + 10)), 600);
return () => clearInterval(timer);
}, []);
return (
<div style={stack}>
<div style={field}>
<label htmlFor="progress-upload">Uploading… {done}%</label>
<Progress id="progress-upload" value={done} max={100} />
</div>
<div style={field}>
{/* No value: indeterminate. */}
<label htmlFor="progress-wait">Waiting for the server</label>
<Progress id="progress-wait" />
</div>
</div>
);
}

Progress is a native <progress>. Give it value and max to show how far along a task is. Leave out value and it is indeterminate: a short bar sweeps across while you wait. The sweep stops under reduced motion.

Name it with a <label> or aria-label, and put the percentage in the text if it matters.

Progress props
PropTypeDefaultDescription
valuenumberHow far along, up to max. Leave it out for an indeterminate bar.
maxnumber1The value that means done.
classNamestringConcatenated with the component's own classes, never replacing them.
renderReactElementElement or component to render instead of the default. Props, className, event handlers and ref are merged onto it.
refRef<HTMLElement>Ref to the rendered element. Merged with any ref on the render element.
…restHTMLAttributesAnything else is spread onto the rendered element, so id, aria-*, data-* and event handlers all reach the DOM.
  • To show how much of a range is used, such as disk space or password strength, use a Meter.
  • Restyle with --progress-height, --progress-track-color and --progress-bar-color.