# Progress (/docs/progress)





## API Reference [#api-reference]

<BaseUIReference href="https://base-ui.com/react/components/progress" />

## Basic [#basic]

<Preview cssProperties="progressPlaygroundCssProperties">
  <ProgressExample />

  <Preview.Code>
    {`
          import {
            Progress,
            ProgressLabel,
            ProgressValue,
          } from "moduix";

          export function ProgressDemo() {
            return (
              <Progress value={24}>
                <ProgressLabel>Export data</ProgressLabel>
                <ProgressValue />
              </Progress>
            );
          }
        `}
  </Preview.Code>

  <Preview.CSSProperties>
    {(context) => <ProgressCssPropertiesPanel {...context} />}
  </Preview.CSSProperties>

  <Preview.CSSPlayground>
    {(context) => <ProgressCssPlaygroundPanel {...context} />}
  </Preview.CSSPlayground>
</Preview>

## Anatomy [#anatomy]

`Progress` groups the text label, formatted value, and visual bar for one long-running task.
The bar structure is rendered automatically so consumers only compose the visible text slots.

```text
Progress[value]
├─ ProgressLabel
├─ ProgressValue
└─ track
   └─ indicator
```

```tsx
import { Progress, ProgressLabel, ProgressValue } from 'moduix';

export function ProgressDemo() {
  return (
    <Progress value={24}>
      <ProgressLabel>Export data</ProgressLabel>
      <ProgressValue />
    </Progress>
  );
}
```

| Part            | Role                                                                                                      |
| --------------- | --------------------------------------------------------------------------------------------------------- |
| `Progress`      | Root state machine. Controls `value`, `min`, `max`, formatting, and accessible progress attributes.       |
| `ProgressLabel` | Optional text label associated with the progress root.                                                    |
| `ProgressValue` | Optional formatted value text. It can render the default formatted value or use a child render function.  |
| `track`         | Internal visual rail rendered by `Progress`. Customize it with CSS variables or `classNames.track`.       |
| `indicator`     | Internal filled bar rendered inside the track. Customize it with CSS variables or `classNames.indicator`. |

`Progress` does not expose `ProgressTrack` or `ProgressIndicator` in the public composition.
Use the default internal bar for normal cases and reach for `classNames` only when slot-level
track or indicator styling is needed.

## Composition [#composition]

Use `value={null}` for indeterminate work, or pass a number with optional `min` and `max` for
known progress. `locale`, `format`, `aria-valuetext`, and `getAriaValueText` come from the root
and keep the visual value and accessibility text aligned.

Style the root with `className`. Style the automatically rendered visual bar with CSS variables,
or pass `classNames={{ track, indicator }}` when the track or indicator needs its own selector.
`ProgressLabel` and `ProgressValue` remain regular visible slots and accept their own `className`
and `render` props from Base UI.

## Examples [#examples]

### Controlled [#controlled]

Keep the value in React state when progress mirrors another control, upload, export, or background task.

<Preview>
  <ControlledProgressExample />

  <Preview.Code>
    {`
          import {
            Progress,
            ProgressLabel,
            ProgressValue,
          } from "moduix";
          import { useState } from "react";

          export function ControlledProgressDemo() {
            const [value, setValue] = useState(45);

            return (
              <div>
                <Progress value={value}>
                  <ProgressLabel>Upload status</ProgressLabel>
                  <ProgressValue />
                </Progress>
                <input
                  type="range"
                  min={0}
                  max={100}
                  value={value}
                  onChange={(event) => {
                    setValue(Number(event.target.value));
                  }}
                />
              </div>
            );
          }
        `}
  </Preview.Code>
</Preview>

### Min Max Range [#min-max-range]

Use `min` and `max` when the current value belongs to a custom range instead of the default `0` to `100`.

<Preview>
  <MinMaxRangeProgressExample />

  <Preview.Code>
    {`
          import {
            Progress,
            ProgressLabel,
            ProgressValue,
          } from "moduix";

          export function MinMaxRangeProgressDemo() {
            return (
              <Progress value={420} min={200} max={800}>
                <ProgressLabel>Requests per minute</ProgressLabel>
                <ProgressValue />
              </Progress>
            );
          }
        `}
  </Preview.Code>
</Preview>

### Locale And Format [#locale-and-format]

Use `locale`, `format`, and a custom `ProgressValue` child function to format progress text for users.

<Preview>
  <LocaleAndFormatProgressExample />

  <Preview.Code>
    {`
          import {
            Progress,
            ProgressLabel,
            ProgressValue,
          } from "moduix";

          export function LocaleAndFormatProgressDemo() {
            return (
              <Progress value={0.64} min={0} max={1} locale="de-DE" format={{ style: "percent" }}>
                <ProgressLabel>Storage usage</ProgressLabel>
                <ProgressValue>{(formattedValue) => \`\${formattedValue} belegt\`}</ProgressValue>
              </Progress>
            );
          }
        `}
  </Preview.Code>
</Preview>

### Indeterminate [#indeterminate]

Pass `value={null}` when the task is running but the current completion percentage is unknown.

<Preview>
  <IndeterminateProgressExample />

  <Preview.Code>
    {`
          import {
            Progress,
            ProgressLabel,
            ProgressValue,
          } from "moduix";

          export function IndeterminateProgressDemo() {
            return (
              <Progress value={null}>
                <ProgressLabel>Preparing report</ProgressLabel>
                <ProgressValue>{() => "In progress"}</ProgressValue>
              </Progress>
            );
          }
        `}
  </Preview.Code>
</Preview>

### Aria Value Text [#aria-value-text]

Use `aria-valuetext` when the numeric value needs a more descriptive accessible label.

<Preview>
  <AriaValueTextProgressExample />

  <Preview.Code>
    {`
          import {
            Progress,
            ProgressLabel,
            ProgressValue,
          } from "moduix";

          export function AriaValueTextProgressDemo() {
            return (
              <Progress value={3} min={0} max={5} aria-valuetext="Step 3 of 5 completed">
                <ProgressLabel>Onboarding</ProgressLabel>
                <ProgressValue>{() => "Step 3 of 5"}</ProgressValue>
              </Progress>
            );
          }
        `}
  </Preview.Code>
</Preview>

### Custom Value Text [#custom-value-text]

Use `getAriaValueText` with custom rendered value text when visual and accessible wording should stay aligned.

<Preview>
  <CustomValueTextProgressExample />

  <Preview.Code>
    {`
          import {
            Progress,
            ProgressLabel,
            ProgressValue,
          } from "moduix";

          export function CustomValueTextProgressDemo() {
            return (
              <Progress
                value={68}
                getAriaValueText={(formattedValue) => \`\${formattedValue} of task completed\`}
              >
                <ProgressLabel>Migration</ProgressLabel>
                <ProgressValue>{(formattedValue) => \`\${formattedValue} done\`}</ProgressValue>
              </Progress>
            );
          }
        `}
  </Preview.Code>
</Preview>

### Custom Styles [#custom-styles]

`Progress` renders the track and indicator automatically. Use `className` for the root and `classNames` for the internal track or indicator slots.

<Preview>
  <CustomStylingProgressExample />

  <Preview.Code>
    {`
          import {
            Progress,
            ProgressLabel,
            ProgressValue,
          } from "moduix";
          import styles from "./progress-demo.module.css";

          export function CustomStylingProgressDemo() {
            return (
              <Progress
                value={72}
                className={styles.customProgress}
                classNames={{ track: styles.customTrack, indicator: styles.customIndicator }}
              >
                <ProgressLabel>Monthly export</ProgressLabel>
                <ProgressValue />
              </Progress>
            );
          }
        `}
  </Preview.Code>

  <Preview.CSS>
    {`
          .customProgress {
            --progress-width: 16rem;
            --progress-track-height: 0.75rem;
            --progress-track-bg: var(--color-accent);
          }

          .customTrack {
            box-shadow: inset 0 0 0 var(--border-width-md)
              color-mix(in oklab, var(--color-primary), transparent 75%);
          }

          .customIndicator {
            background: linear-gradient(90deg, var(--color-primary), var(--color-chart-2));
          }
        `}
  </Preview.CSS>
</Preview>
