

<Preview name="ProgressWithStatusExample" />

## Overview [#overview]

The Progress component provides a visual representation of task completion or progress. It supports both determinate progress (with a known value) and indeterminate progress (when the completion time is unknown).

## Usage [#usage]

```tsx
import {
  Progress,
  ProgressValue,
  ProgressCircle,
  ProgressRadial,
} from "@tilt-legal/cubitt-components/primitives";

// Linear progress
<Progress value={45}>
  <ProgressValue />
</Progress>

// Circular progress
<ProgressCircle value={75} showValue />

// Radial progress (half circle gauge)
<ProgressRadial value={60} startAngle={180} endAngle={360} showValue />
```

## Examples [#examples]

### Sizes [#sizes]

Customize the height of the progress bar.

<Tabs items="[&#x22;Preview&#x22;, &#x22;Code&#x22;]">
  <Tab value="Preview">
    <Preview name="ProgressSizesExample" />
  </Tab>

  <Tab value="Code">
    ```tsx
    import { Progress, ProgressValue } from "@tilt-legal/cubitt-components/primitives";
    import { ProgressValue } from "@tilt-legal/cubitt-components/primitives";
    import {
      useEffect,
      useState } from "react";

    export default function Example() {
      const [progress,
      setProgress] = useState(45);

      useEffect(() => {
        const timer = setTimeout(() => setProgress(75),
      500);
        return () => clearTimeout(timer);
      },
      []);

      return (
        <div className="space-y-6 w-80">
          <div className="space-y-2">
            <h3 className="text-sm font-medium">Small</h3>
            <Progress value={progress} className="h-1">
              <ProgressValue />
            </Progress>
          </div>
          <div className="space-y-2">
            <h3 className="text-sm font-medium">Medium (Default)</h3>
            <Progress value={progress}>
              <ProgressValue />
            </Progress>
          </div>
          <div className="space-y-2">
            <h3 className="text-sm font-medium">Large</h3>
            <Progress value={progress} className="h-3">
              <ProgressValue />
            </Progress>
          </div>
        </div>
      );
    }
    ```
  </Tab>
</Tabs>

### Animated [#animated]

Animate the progress value over time.

<Tabs
  items="[&#x22;Preview&#x22;,
    &#x22;Code&#x22;]"
>
  <Tab value="Preview">
    <Preview name="AnimatedProgressExample" />
  </Tab>

  <Tab value="Code">
    ```tsx
    import { Progress } from "@tilt-legal/cubitt-components/primitives";
    import {
      useEffect,
      useState } from "react";

    export default function Example() {
      const [progress,
      setProgress] = useState(0);

      useEffect(() => {
        const timer = setInterval(() => {
          setProgress((prev) => {
            if (prev >= 100) {
              return 0;
            }
            return prev + 10;
          });
        },
      500);

        return () => clearInterval(timer);
      },
      []);

      return (
        <Progress value={progress}>
          <ProgressValue />
        </Progress>
      );
    }
    ```
  </Tab>
</Tabs>

### With Status [#with-status]

Show contextual status messages during progress updates.

<Tabs
  items="[&#x22;Preview&#x22;,
    &#x22;Code&#x22;]"
>
  <Tab value="Preview">
    <Preview name="ProgressWithStatusExample" />
  </Tab>

  <Tab value="Code">
    ```tsx
    import { Progress } from "@tilt-legal/cubitt-components/primitives";
    import {
      useEffect,
      useState } from "react";

    export default function Example() {
      const [downloadProgress,
      setDownloadProgress] = useState(0);

      const getStatusMessage = (progress: number) => {
        if (progress < 5) return "Initializing download...";
        if (progress < 15) return "Setting up environment...";
        if (progress < 25) return "Connecting to server...";
        if (progress < 35) return "Verifying permissions...";
        if (progress < 50) return "Downloading core files...";
        if (progress < 65) return "Downloading assets...";
        if (progress < 80) return "Downloading dependencies...";
        if (progress < 90) return "Extracting files...";
        if (progress < 95) return "Validating integrity...";
        if (progress < 100) return "Finalizing installation...";
        return "Download complete!";
      };

      useEffect(() => {
        const downloadTimer = setInterval(() => {
          setDownloadProgress((prev) => {
            if (prev >= 100) {
              return 0;
            }
            return prev + Math.random() * 3 + 1;
          });
        },
      150);

        return () => clearInterval(downloadTimer);
      },
      []);

      return (
        <div className="w-80 space-y-2">
          <div className="flex justify-between text-sm">
            <span>Workspace Setup</span>
            <span className="text-muted-foreground">
              {Math.round(downloadProgress)}%
            </span>
          </div>
          <Progress value={downloadProgress} />
          <div className="text-xs text-muted-foreground">
            {getStatusMessage(downloadProgress)}
          </div>
        </div>
      );
    }
    ```
  </Tab>
</Tabs>

### Circular Progress [#circular-progress]

Show progress as a full circle with custom content in the center.

<Tabs
  items="[&#x22;Preview&#x22;,
    &#x22;Code&#x22;]"
>
  <Tab value="Preview">
    <Preview name="ProgressCircleCPUExample" />
  </Tab>

  <Tab value="Code">
    ```tsx
    import { ProgressCircle } from "@tilt-legal/cubitt-components/primitives";
    import {
      useEffect,
      useState } from "react";

    export default function Example() {
      const [cpuUsage,
      setCpuUsage] = useState(0);

      useEffect(() => {
        // CPU usage simulation
        const cpuTimer = setInterval(() => {
          setCpuUsage((prev) => {
            const target = 30 + Math.sin(Date.now() / 3000) * 20 + Math.random() * 15;
            return prev + (target - prev) * 0.1;
          });
        },
      100);

        return () => {
          clearInterval(cpuTimer);
        };
      },
      []);

      return (
        <div className="flex items-center justify-center">
          <div className="flex flex-col items-center gap-3">
            <ProgressCircle
              value={cpuUsage}
              size={80}
              strokeWidth={6}
              className="text-fuchsia-500"
              indicatorClassName="text-fuchsia-500"
            >
              <div className="text-center">
                <div className="text-base font-bold">{Math.round(cpuUsage)}%</div>
                <div className="text-xs text-muted-foreground">CPU</div>
              </div>
            </ProgressCircle>
            <span className="text-xs text-muted-foreground">Processor Usage</span>
          </div>
        </div>
      );
    }
    ```
  </Tab>
</Tabs>

### Radial Progress [#radial-progress]

Show progress as a partial arc with custom angles (great for gauges and speedometers).

<Tabs
  items="[&#x22;Preview&#x22;,
    &#x22;Code&#x22;]"
>
  <Tab value="Preview">
    <Preview name="ProgressRadialUploadExample" />
  </Tab>

  <Tab value="Code">
    ```tsx
    import { ProgressRadial } from "@tilt-legal/cubitt-components/primitives";
    import { useEffect, useState } from "react";

    export default function Example() {
      const [taskProgress, setTaskProgress] = useState(0);

      useEffect(() => {
        const taskTimer = setInterval(() => {
          setTaskProgress((prev) => {
            if (prev >= 100) {
              return 0;
            }
            return prev + Math.random() * 2 + 0.5;
          });
        }, 200);

        return () => {
          clearInterval(taskTimer);
        };
      }, []);

      return (
        <div className="flex items-center justify-center">
          <div className="flex flex-col items-center gap-3">
            <ProgressRadial
              value={taskProgress}
              size={80}
              startAngle={180}
              endAngle={360}
              strokeWidth={5}
              indicatorClassName="text-green-500"
            >
              <div className="text-center">
                <div className="text-base font-bold">{Math.round(taskProgress)}%</div>
                <div className="text-xs text-muted-foreground">Upload</div>
              </div>
            </ProgressRadial>
            <span className="text-xs text-muted-foreground">Upload Status</span>
          </div>
        </div>
      );
    }
    ```
  </Tab>
</Tabs>

***

## API Reference [#api-reference]

### Progress [#progress]

The root component that displays the progress bar.

| Prop               | Type                                      | Default | Description                                                                    |
| ------------------ | ----------------------------------------- | ------- | ------------------------------------------------------------------------------ |
| `value`            | `number \| null`                          | —       | The current progress value. Use `null` for indeterminate progress.             |
| `min`              | `number`                                  | `0`     | The minimum value.                                                             |
| `max`              | `number`                                  | `100`   | The maximum value.                                                             |
| `getAriaValueText` | `(value: number) => string`               | —       | Function returning human-readable text for the current progress value.         |
| `aria-valuetext`   | `string`                                  | —       | A string value that provides a user-friendly name for the current value.       |
| `locale`           | `Intl.LocalesArgument`                    | —       | The locale used by `Intl.NumberFormat` when formatting the value.              |
| `format`           | `Intl.NumberFormatOptions`                | —       | Options to format the value.                                                   |
| `className`        | `string \| (state) => string`             | —       | CSS classes or function that returns classes based on component state.         |
| `render`           | `ReactElement \| (props) => ReactElement` | —       | Allows composing the component with another element. Receives props to spread. |
| `children`         | `ReactNode`                               | —       | Child elements (typically ProgressValue).                                      |

### ProgressValue [#progressvalue]

Displays the formatted progress value (used with linear Progress).

| Prop        | Type                                      | Description                                                                    |
| ----------- | ----------------------------------------- | ------------------------------------------------------------------------------ |
| `className` | `string \| (state) => string`             | CSS classes or function that returns classes based on component state.         |
| `render`    | `ReactElement \| (props) => ReactElement` | Allows composing the component with another element. Receives props to spread. |

### ProgressCircle [#progresscircle]

Circular progress indicator (full 360° circle) built with SVG.

| Prop                 | Type        | Default | Description                                                    |
| -------------------- | ----------- | ------- | -------------------------------------------------------------- |
| `value`              | `number`    | `0`     | Progress value from 0 to 100.                                  |
| `size`               | `number`    | `48`    | Size of the circle in pixels.                                  |
| `strokeWidth`        | `number`    | `4`     | Width of the progress stroke.                                  |
| `showValue`          | `boolean`   | `false` | Whether to show the percentage value in the center.            |
| `indicatorClassName` | `string`    | —       | Additional className for the progress indicator stroke.        |
| `trackClassName`     | `string`    | —       | Additional className for the progress track.                   |
| `className`          | `string`    | —       | Additional CSS classes for the container.                      |
| `children`           | `ReactNode` | —       | Custom content to display in the center (overrides showValue). |

### ProgressRadial [#progressradial]

Radial progress indicator (partial arc/gauge) built with SVG.

| Prop                 | Type        | Default | Description                                                    |
| -------------------- | ----------- | ------- | -------------------------------------------------------------- |
| `value`              | `number`    | `0`     | Progress value from 0 to 100.                                  |
| `size`               | `number`    | `120`   | Size of the radial in pixels.                                  |
| `strokeWidth`        | `number`    | `8`     | Width of the progress stroke.                                  |
| `startAngle`         | `number`    | `-90`   | Start angle in degrees (-90 is top, 0 is right).               |
| `endAngle`           | `number`    | `90`    | End angle in degrees (90 is bottom, 180 is left).              |
| `showValue`          | `boolean`   | `false` | Whether to show the percentage value in the center.            |
| `indicatorClassName` | `string`    | —       | Additional className for the progress indicator stroke.        |
| `trackClassName`     | `string`    | —       | Additional className for the progress track.                   |
| `className`          | `string`    | —       | Additional CSS classes for the container.                      |
| `children`           | `ReactNode` | —       | Custom content to display in the center (overrides showValue). |

### Notes [#notes]

* **Linear Progress** uses Base UI primitives for accessibility and proper ARIA attributes
* **ProgressCircle** is ideal for compact progress indicators, dashboards, and metrics
* **ProgressRadial** is perfect for gauges, speedometers, and partial progress arcs
* Both circular components support custom content in the center via `children` prop
* Use `showValue` for automatic percentage display, or `children` for custom content
* The `indicatorClassName` and `trackClassName` props allow full color customization using Tailwind's `text-*` classes
