implement
Progress

Progress

How far along a task is, or that it is running at all.

Uploading photos13%
import { Div, ImplementLifecycle, signal, Span } from "@implementjs/core";
import { Progress } from "@/lib/components/ui/progress";

export default function ProgressDemo() {
	const value = signal<number | null>(13);

	return Div(
		{ class: "flex w-full max-w-sm flex-col gap-2" },
		ImplementLifecycle({
			onMount: () => {
				const timer = setInterval(() => {
					value.update((v) => (v === null || v >= 100 ? 13 : Math.min(100, v + 29)));
				}, 1000);
				return () => clearInterval(timer);
			},
		}),
		Div(
			{ class: "flex items-center justify-between text-sm font-medium" },
			Span({ id: "upload-label" }, "Uploading photos"),
			Span(
				{ class: "tabular-nums" },
				value.bind((v) => `${v ?? 0}%`),
			),
		),
		Progress({ "aria-labelledby": "upload-label", value }),
	);
}

Installation

npx jsrepo add @implementjs/ui/progress

Nothing else comes with it — this one stands alone on @implementjs/core and @implementjs/primitives.

Usage

A task that starts and finishes: an upload, an import, a build. For a standing measurement, use meter.

The wrapper renders the indicator and drives it from value, min, and max. Pass value: null for a task whose length is unknown — the bar fills and pulses instead of showing a position.

import { signal } from "@implementjs/core";
import { Progress } from "@/lib/components/ui/progress";

const value = signal(13);

Progress({ value, "aria-label": "Uploading photos" });

Indeterminate

Progress({ value: null, "aria-label": "Importing" });

The primitive sets data-indeterminate on the root, and the indicator animates on it. motion-reduce is respected through Tailwind's own variant on the transition.

API Reference

Every prop the styling does not consume is forwarded to the Progress primitive, so the tables below are the whole surface — the behavior props and the styling ones together.

Progress

Completion status of a task. Sets role="progressbar" and the aria value attributes. Give it a track and a fill; it handles the semantics. Styled as a rounded track. The wrapper renders the indicator inside it; an indeterminate bar pulses at full width instead of showing a position. Renders a Div; extra props are forwarded onto it.

PropTypeDefaultDescription
valueSignal<number | null> | number | null0The current value; null renders an indeterminate bar. Pass a signal to control it from outside; a number seeds uncontrolled state.
minSignal<number> | number0The value the bar starts from.
maxSignal<number> | number100The value at which the task is complete.
Data attributeValue
[data-progress-root]Present
[data-state]"loading" | "loaded" | "indeterminate"
[data-value]The current value; absent while indeterminate
[data-min]The minimum value
[data-max]The maximum value
[data-indeterminate]Present while the value is null