Progress

A horizontal bar that conveys task completion or an indeterminate loading state.

<Progress value={60} className="w-full max-w-md" />

Usage

import { Progress } from "@reva/ui";

Pass a numeric value (0–100) for a determinate bar. Omit value (or pass null) to show an indeterminate animation. The track uses bg-muted and the indicator uses bg-primary-solid, so colour follows the active theme tokens.

Examples

Determinate

A controlled bar that animates from 0 → 100 and resets, paired with a numeric label.

Loading…

0%

"use client";import { HStack, Progress, Text, VStack } from "@reva/ui";import * as React from "react";export function ProgressDeterminateDemo() {const [value, setValue] = React.useState(0);React.useEffect(() => {  const interval = setInterval(() => {    setValue((v) => (v >= 100 ? 0 : v + 5));  }, 400);  return () => clearInterval(interval);}, []);return (  <VStack className="w-full max-w-md" gap={3}>    <HStack align="center" justify="between">      <Text className="text-sm">Loading…</Text>      <Text className="text-sm text-fg-muted">{value}%</Text>    </HStack>    <Progress value={value} />  </VStack>);}

Indeterminate

Omit value (or pass null) when the duration is unknown. The indicator uses the animate-progress-indeterminate keyframes defined in theme.css.

<Progress className="w-full max-w-md" />

With label

Compose a header row with HStack above the bar — the bar itself stays purely visual, so render the percentage (or status text) alongside it.

Uploading files

72%

<VStack gap={3} className="w-full max-w-md">  <HStack align="center" justify="between">    <Text className="text-sm font-medium">Uploading files</Text>    <Text className="text-sm text-fg-muted">72%</Text>  </HStack>  <Progress value={72} /></VStack>

Sizes

Use the size prop to pick a thicker or thinner bar — sm (4px), default (6px), lg (8px).

<VStack gap={4} className="w-full max-w-md">  <Progress size="sm" value={40} />  <Progress value={60} />  <Progress size="lg" value={80} /></VStack>

Stepped control

Drive the bar from external controls — useful for multi-step flows or manual progress indicators.

"use client";import { Button, HStack, Progress, VStack } from "@reva/ui";import * as React from "react";export function ProgressSteppedDemo() {const [value, setValue] = React.useState(40);return (  <VStack className="w-full max-w-md" gap={4}>    <Progress value={value} />    <HStack gap={2} justify="center">      <Button size="sm" type="button" variant="secondary" onClick={() => setValue((v) => Math.max(0, v - 10))}>        −10      </Button>      <Button size="sm" type="button" variant="secondary" onClick={() => setValue((v) => Math.min(100, v + 10))}>        +10      </Button>    </HStack>  </VStack>);}

Props

Progress extends Radix Progress.Root with size.

PropTypeDefaultDescription
valuenumber | nullnullProgress value (0–100). Pass null or omit for indeterminate.
size"sm" | "default" | "lg""default"Track height — sm (h-1), default (h-1.5), lg (h-2).
maxnumber100Maximum value (forwarded to Radix).
getValueLabel(value: number, max: number) => stringCustom label for assistive tech.
classNamestringMerged onto the track via cn().

Radix exposes data-state ("loading" / "complete" / "indeterminate") and data-value on the root for state-driven styling. Other root props are forwarded.

On this page