---
title: Progress
description: Visual indicator of completion or loading state.
icon: bars-progress
---

import { ComponentPreview } from '/snippets/component-preview.mdx'

Progress bars show how far along a process is. They fill from left to right as `value` approaches `max`.

## Basic Usage

<ComponentPreview json={{"view":{"type":"Progress","value":60.0,"variant":"default","size":"default"}}} playground="ZnJvbSBwcmVmYWJfdWkuY29tcG9uZW50cyBpbXBvcnQgUHJvZ3Jlc3MKClByb2dyZXNzKHZhbHVlPTYwKQo">
<CodeGroup>
```python Python icon="python"
from prefab_ui.components import Progress

Progress(value=60)
```
```json Protocol icon="brackets-curly"
{
  "view": {"type": "Progress", "value": 60.0, "variant": "default", "size": "default"}
}
```
</CodeGroup>
</ComponentPreview>

## Range

By default `max` is 100 and `min` is 0, but you can set either to define a custom range. The renderer normalizes the value to a percentage automatically. Set `max` for step-style counting, or use both `min` and `max` when the range doesn't start at zero.

<ComponentPreview json={{"view":{"cssClass":"gap-4","type":"Column","children":[{"cssClass":"gap-2","type":"Column","children":[{"type":"Label","text":"3 of 5 steps"},{"type":"Progress","value":3.0,"max":5.0,"variant":"default","size":"default"}]},{"cssClass":"gap-2","type":"Column","children":[{"type":"Label","text":"Temperature: 72\u00b0F (range 60\u2013100)"},{"type":"Progress","value":72.0,"min":60.0,"max":100.0,"variant":"warning","size":"default"}]}]}}} playground="ZnJvbSBwcmVmYWJfdWkuY29tcG9uZW50cyBpbXBvcnQgQ29sdW1uLCBMYWJlbCwgUHJvZ3Jlc3MKCndpdGggQ29sdW1uKGdhcD00KToKICAgIHdpdGggQ29sdW1uKGdhcD0yKToKICAgICAgICBMYWJlbCgiMyBvZiA1IHN0ZXBzIikKICAgICAgICBQcm9ncmVzcyh2YWx1ZT0zLCBtYXg9NSkKICAgIHdpdGggQ29sdW1uKGdhcD0yKToKICAgICAgICBMYWJlbCgiVGVtcGVyYXR1cmU6IDcywrBGIChyYW5nZSA2MOKAkzEwMCkiKQogICAgICAgIFByb2dyZXNzKHZhbHVlPTcyLCBtaW49NjAsIG1heD0xMDAsIHZhcmlhbnQ9Indhcm5pbmciKQo">
<CodeGroup>
```python Python icon="python"
from prefab_ui.components import Column, Label, Progress

with Column(gap=4):
    with Column(gap=2):
        Label("3 of 5 steps")
        Progress(value=3, max=5)
    with Column(gap=2):
        Label("Temperature: 72°F (range 60–100)")
        Progress(value=72, min=60, max=100, variant="warning")
```
```json Protocol icon="brackets-curly"
{
  "view": {
    "cssClass": "gap-4",
    "type": "Column",
    "children": [
      {
        "cssClass": "gap-2",
        "type": "Column",
        "children": [
          {"type": "Label", "text": "3 of 5 steps"},
          {
            "type": "Progress",
            "value": 3.0,
            "max": 5.0,
            "variant": "default",
            "size": "default"
          }
        ]
      },
      {
        "cssClass": "gap-2",
        "type": "Column",
        "children": [
          {"type": "Label", "text": "Temperature: 72\u00b0F (range 60\u2013100)"},
          {
            "type": "Progress",
            "value": 72.0,
            "min": 60.0,
            "max": 100.0,
            "variant": "warning",
            "size": "default"
          }
        ]
      }
    ]
  }
}
```
</CodeGroup>
</ComponentPreview>

## Variants

Semantic variants color the progress bar to communicate meaning at a glance:

<ComponentPreview json={{"view":{"cssClass":"gap-4","type":"Column","children":[{"cssClass":"gap-2","type":"Column","children":[{"type":"Label","text":"Default"},{"type":"Progress","value":60.0,"variant":"default","size":"default"}]},{"cssClass":"gap-2","type":"Column","children":[{"type":"Label","text":"Success"},{"type":"Progress","value":100.0,"variant":"success","size":"default"}]},{"cssClass":"gap-2","type":"Column","children":[{"type":"Label","text":"Warning"},{"type":"Progress","value":72.0,"variant":"warning","size":"default"}]},{"cssClass":"gap-2","type":"Column","children":[{"type":"Label","text":"Destructive"},{"type":"Progress","value":90.0,"variant":"destructive","size":"default"}]},{"cssClass":"gap-2","type":"Column","children":[{"type":"Label","text":"Info"},{"type":"Progress","value":45.0,"variant":"info","size":"default"}]},{"cssClass":"gap-2","type":"Column","children":[{"type":"Label","text":"Muted"},{"type":"Progress","value":30.0,"variant":"muted","size":"default"}]}]}}} playground=" ">
<CodeGroup>
```python Python icon="python"
from prefab_ui.components import Column, Label, Progress

with Column(gap=4):
    with Column(gap=2):
        Label("Default")
        Progress(value=60)
    with Column(gap=2):
        Label("Success")
        Progress(value=100, variant="success")
    with Column(gap=2):
        Label("Warning")
        Progress(value=72, variant="warning")
    with Column(gap=2):
        Label("Destructive")
        Progress(value=90, variant="destructive")
    with Column(gap=2):
        Label("Info")
        Progress(value=45, variant="info")
    with Column(gap=2):
        Label("Muted")
        Progress(value=30, variant="muted")
```
```json Protocol icon="brackets-curly"
{
  "view": {
    "cssClass": "gap-4",
    "type": "Column",
    "children": [
      {
        "cssClass": "gap-2",
        "type": "Column",
        "children": [
          {"type": "Label", "text": "Default"},
          {"type": "Progress", "value": 60.0, "variant": "default", "size": "default"}
        ]
      },
      {
        "cssClass": "gap-2",
        "type": "Column",
        "children": [
          {"type": "Label", "text": "Success"},
          {"type": "Progress", "value": 100.0, "variant": "success", "size": "default"}
        ]
      },
      {
        "cssClass": "gap-2",
        "type": "Column",
        "children": [
          {"type": "Label", "text": "Warning"},
          {"type": "Progress", "value": 72.0, "variant": "warning", "size": "default"}
        ]
      },
      {
        "cssClass": "gap-2",
        "type": "Column",
        "children": [
          {"type": "Label", "text": "Destructive"},
          {"type": "Progress", "value": 90.0, "variant": "destructive", "size": "default"}
        ]
      },
      {
        "cssClass": "gap-2",
        "type": "Column",
        "children": [
          {"type": "Label", "text": "Info"},
          {"type": "Progress", "value": 45.0, "variant": "info", "size": "default"}
        ]
      },
      {
        "cssClass": "gap-2",
        "type": "Column",
        "children": [
          {"type": "Label", "text": "Muted"},
          {"type": "Progress", "value": 30.0, "variant": "muted", "size": "default"}
        ]
      }
    ]
  }
}
```
</CodeGroup>
</ComponentPreview>

## Sizes

Control the bar thickness with `size`. The default is a medium weight suitable for most layouts; use `sm` for compact spaces and `lg` for dashboard-style data displays:

<ComponentPreview json={{"view":{"cssClass":"gap-4","type":"Column","children":[{"cssClass":"gap-2","type":"Column","children":[{"type":"Label","text":"Small"},{"type":"Progress","value":60.0,"variant":"default","size":"sm"}]},{"cssClass":"gap-2","type":"Column","children":[{"type":"Label","text":"Default"},{"type":"Progress","value":60.0,"variant":"default","size":"default"}]},{"cssClass":"gap-2","type":"Column","children":[{"type":"Label","text":"Large"},{"type":"Progress","value":60.0,"variant":"default","size":"lg"}]}]}}} playground="ZnJvbSBwcmVmYWJfdWkuY29tcG9uZW50cyBpbXBvcnQgQ29sdW1uLCBMYWJlbCwgUHJvZ3Jlc3MKCndpdGggQ29sdW1uKGdhcD00KToKICAgIHdpdGggQ29sdW1uKGdhcD0yKToKICAgICAgICBMYWJlbCgiU21hbGwiKQogICAgICAgIFByb2dyZXNzKHZhbHVlPTYwLCBzaXplPSJzbSIpCiAgICB3aXRoIENvbHVtbihnYXA9Mik6CiAgICAgICAgTGFiZWwoIkRlZmF1bHQiKQogICAgICAgIFByb2dyZXNzKHZhbHVlPTYwKQogICAgd2l0aCBDb2x1bW4oZ2FwPTIpOgogICAgICAgIExhYmVsKCJMYXJnZSIpCiAgICAgICAgUHJvZ3Jlc3ModmFsdWU9NjAsIHNpemU9ImxnIikK">
<CodeGroup>
```python Python icon="python"
from prefab_ui.components import Column, Label, Progress

with Column(gap=4):
    with Column(gap=2):
        Label("Small")
        Progress(value=60, size="sm")
    with Column(gap=2):
        Label("Default")
        Progress(value=60)
    with Column(gap=2):
        Label("Large")
        Progress(value=60, size="lg")
```
```json Protocol icon="brackets-curly"
{
  "view": {
    "cssClass": "gap-4",
    "type": "Column",
    "children": [
      {
        "cssClass": "gap-2",
        "type": "Column",
        "children": [
          {"type": "Label", "text": "Small"},
          {"type": "Progress", "value": 60.0, "variant": "default", "size": "sm"}
        ]
      },
      {
        "cssClass": "gap-2",
        "type": "Column",
        "children": [
          {"type": "Label", "text": "Default"},
          {"type": "Progress", "value": 60.0, "variant": "default", "size": "default"}
        ]
      },
      {
        "cssClass": "gap-2",
        "type": "Column",
        "children": [
          {"type": "Label", "text": "Large"},
          {"type": "Progress", "value": 60.0, "variant": "default", "size": "lg"}
        ]
      }
    ]
  }
}
```
</CodeGroup>
</ComponentPreview>

## Custom Colors

Use `indicator_class` for arbitrary colors beyond the built-in variants:

<ComponentPreview json={{"view":{"cssClass":"gap-4","type":"Column","children":[{"cssClass":"gap-2","type":"Column","children":[{"type":"Label","text":"Storage Used"},{"cssClass":"pf-progress-flat","type":"Progress","value":85.0,"variant":"default","size":"default","indicatorClass":"bg-red-500"}]},{"cssClass":"gap-2","type":"Column","children":[{"type":"Label","text":"Upload Progress"},{"cssClass":"pf-progress-flat","type":"Progress","value":45.0,"variant":"default","size":"default","indicatorClass":"bg-blue-500"}]},{"cssClass":"gap-2","type":"Column","children":[{"type":"Label","text":"Tasks Complete"},{"cssClass":"pf-progress-flat","type":"Progress","value":100.0,"variant":"default","size":"default","indicatorClass":"bg-green-500"}]}]}}} playground=" ">
<CodeGroup>
```python Python icon="python"
from prefab_ui.components import Column, Label, Progress

with Column(gap=4):
    with Column(gap=2):
        Label("Storage Used")
        Progress(value=85, indicator_class="bg-red-500")
    with Column(gap=2):
        Label("Upload Progress")
        Progress(value=45, indicator_class="bg-blue-500")
    with Column(gap=2):
        Label("Tasks Complete")
        Progress(value=100, indicator_class="bg-green-500")
```
```json Protocol icon="brackets-curly"
{
  "view": {
    "cssClass": "gap-4",
    "type": "Column",
    "children": [
      {
        "cssClass": "gap-2",
        "type": "Column",
        "children": [
          {"type": "Label", "text": "Storage Used"},
          {
            "cssClass": "pf-progress-flat",
            "type": "Progress",
            "value": 85.0,
            "variant": "default",
            "size": "default",
            "indicatorClass": "bg-red-500"
          }
        ]
      },
      {
        "cssClass": "gap-2",
        "type": "Column",
        "children": [
          {"type": "Label", "text": "Upload Progress"},
          {
            "cssClass": "pf-progress-flat",
            "type": "Progress",
            "value": 45.0,
            "variant": "default",
            "size": "default",
            "indicatorClass": "bg-blue-500"
          }
        ]
      },
      {
        "cssClass": "gap-2",
        "type": "Column",
        "children": [
          {"type": "Label", "text": "Tasks Complete"},
          {
            "cssClass": "pf-progress-flat",
            "type": "Progress",
            "value": 100.0,
            "variant": "default",
            "size": "default",
            "indicatorClass": "bg-green-500"
          }
        ]
      }
    ]
  }
}
```
</CodeGroup>
</ComponentPreview>

## Target Marker

The `target` prop renders a vertical marker line on the bar at a specific position, so you can compare actual progress against a goal. Set `max` to the ceiling of the gauge so both `value` and `target` land at meaningful positions. Use `target_class` to style the marker.

<ComponentPreview json={{"view":{"cssClass":"gap-4","type":"Column","children":[{"cssClass":"gap-2","type":"Column","children":[{"type":"Label","text":"Below target"},{"type":"Progress","value":55.0,"variant":"default","size":"default","target":75.0}]},{"cssClass":"gap-2","type":"Column","children":[{"type":"Label","text":"Custom target style"},{"cssClass":"pf-progress-flat","type":"Progress","value":50.0,"variant":"default","size":"default","target":75.0,"indicatorClass":"bg-pink-400","targetClass":"bg-pink-400"}]}]}}} playground=" ">
<CodeGroup>
```python Python icon="python"
from prefab_ui.components import Column, Label, Progress

with Column(gap=4):
    with Column(gap=2):
        Label("Below target")
        Progress(value=55, target=75)
    with Column(gap=2):
        Label("Custom target style")
        Progress(
            value=50, 
            target=75,
            indicator_class="bg-pink-400",
            target_class="bg-pink-400",
        )
```
```json Protocol icon="brackets-curly"
{
  "view": {
    "cssClass": "gap-4",
    "type": "Column",
    "children": [
      {
        "cssClass": "gap-2",
        "type": "Column",
        "children": [
          {"type": "Label", "text": "Below target"},
          {
            "type": "Progress",
            "value": 55.0,
            "variant": "default",
            "size": "default",
            "target": 75.0
          }
        ]
      },
      {
        "cssClass": "gap-2",
        "type": "Column",
        "children": [
          {"type": "Label", "text": "Custom target style"},
          {
            "cssClass": "pf-progress-flat",
            "type": "Progress",
            "value": 50.0,
            "variant": "default",
            "size": "default",
            "target": 75.0,
            "indicatorClass": "bg-pink-400",
            "targetClass": "bg-pink-400"
          }
        ]
      }
    ]
  }
}
```
</CodeGroup>
</ComponentPreview>

## Vertical Orientation

Set `orientation="vertical"` for vertical progress bars. The default height is set by the theme — wrap in a sized container for custom heights:

<ComponentPreview json={{"view":{"cssClass":"gap-8 h-48 items-end justify-center","type":"Row","children":[{"type":"Progress","value":75.0,"variant":"default","size":"default","orientation":"vertical"},{"type":"Progress","value":50.0,"variant":"success","size":"default","target":80.0,"orientation":"vertical"},{"type":"Progress","value":25.0,"variant":"info","size":"default","orientation":"vertical"}]}}} playground="ZnJvbSBwcmVmYWJfdWkuY29tcG9uZW50cyBpbXBvcnQgUHJvZ3Jlc3MsIFJvdwoKd2l0aCBSb3coY3NzX2NsYXNzPSJnYXAtOCBoLTQ4IGl0ZW1zLWVuZCBqdXN0aWZ5LWNlbnRlciIpOgogICAgUHJvZ3Jlc3ModmFsdWU9NzUsIG9yaWVudGF0aW9uPSJ2ZXJ0aWNhbCIpCiAgICBQcm9ncmVzcyh2YWx1ZT01MCwgdGFyZ2V0PTgwLCB2YXJpYW50PSJzdWNjZXNzIiwgb3JpZW50YXRpb249InZlcnRpY2FsIikKICAgIFByb2dyZXNzKHZhbHVlPTI1LCB2YXJpYW50PSJpbmZvIiwgb3JpZW50YXRpb249InZlcnRpY2FsIikK">
<CodeGroup>
```python Python icon="python"
from prefab_ui.components import Progress, Row

with Row(css_class="gap-8 h-48 items-end justify-center"):
    Progress(value=75, orientation="vertical")
    Progress(value=50, target=80, variant="success", orientation="vertical")
    Progress(value=25, variant="info", orientation="vertical")
```
```json Protocol icon="brackets-curly"
{
  "view": {
    "cssClass": "gap-8 h-48 items-end justify-center",
    "type": "Row",
    "children": [
      {
        "type": "Progress",
        "value": 75.0,
        "variant": "default",
        "size": "default",
        "orientation": "vertical"
      },
      {
        "type": "Progress",
        "value": 50.0,
        "variant": "success",
        "size": "default",
        "target": 80.0,
        "orientation": "vertical"
      },
      {
        "type": "Progress",
        "value": 25.0,
        "variant": "info",
        "size": "default",
        "orientation": "vertical"
      }
    ]
  }
}
```
</CodeGroup>
</ComponentPreview>

## Dynamic Progress with Labels

Bind a slider to a progress bar so the label reflects the actual value. Forward-declare the reactive reference with a lambda so it can be used before the slider appears in the tree:

<ComponentPreview json={{"view":{"cssClass":"gap-3","type":"Column","children":[{"cssClass":"justify-between items-center","type":"Row","children":[{"content":"Upload progress","type":"Text"},{"cssClass":"font-bold","content":"{{ slider_1 | percent }}","type":"Text"}]},{"type":"Progress","value":"{{ slider_1 }}","max":1.0,"variant":"default","size":"default"},{"name":"slider_1","value":0.65,"type":"Slider","min":0.0,"max":1.0,"step":0.01,"disabled":false,"size":"default"}]},"state":{"slider_1":0.65}}} playground="ZnJvbSBwcmVmYWJfdWkuY29tcG9uZW50cyBpbXBvcnQgQ29sdW1uLCBQcm9ncmVzcywgUm93LCBTbGlkZXIsIFRleHQKZnJvbSBwcmVmYWJfdWkucnggaW1wb3J0IFJ4Cgp2YWwgPSBSeChsYW1iZGE6IHNsaWRlcikKCndpdGggQ29sdW1uKGdhcD0zKToKICAgIHdpdGggUm93KGNzc19jbGFzcz0ianVzdGlmeS1iZXR3ZWVuIGl0ZW1zLWNlbnRlciIpOgogICAgICAgIFRleHQoIlVwbG9hZCBwcm9ncmVzcyIpCiAgICAgICAgVGV4dCh2YWwucGVyY2VudCgpLCBib2xkPVRydWUpCiAgICBQcm9ncmVzcyh2YWx1ZT12YWwsIG1heD0xKQogICAgc2xpZGVyID0gU2xpZGVyKG1pbj0wLCBtYXg9MSwgc3RlcD0wLjAxLCB2YWx1ZT0wLjY1KQo">
<CodeGroup>
```python Python icon="python"
from prefab_ui.components import Column, Progress, Row, Slider, Text
from prefab_ui.rx import Rx

val = Rx(lambda: slider)

with Column(gap=3):
    with Row(css_class="justify-between items-center"):
        Text("Upload progress")
        Text(val.percent(), bold=True)
    Progress(value=val, max=1)
    slider = Slider(min=0, max=1, step=0.01, value=0.65)
```
```json Protocol icon="brackets-curly"
{
  "view": {
    "cssClass": "gap-3",
    "type": "Column",
    "children": [
      {
        "cssClass": "justify-between items-center",
        "type": "Row",
        "children": [
          {"content": "Upload progress", "type": "Text"},
          {"cssClass": "font-bold", "content": "{{ slider_1 | percent }}", "type": "Text"}
        ]
      },
      {
        "type": "Progress",
        "value": "{{ slider_1 }}",
        "max": 1.0,
        "variant": "default",
        "size": "default"
      },
      {
        "name": "slider_1",
        "value": 0.65,
        "type": "Slider",
        "min": 0.0,
        "max": 1.0,
        "step": 0.01,
        "disabled": false,
        "size": "default"
      }
    ]
  },
  "state": {"slider_1": 0.65}
}
```
</CodeGroup>
</ComponentPreview>

## API Reference

<Card icon="code" title="Progress Parameters">
<ParamField body="value" type="float | str" default="0">
  Current progress value. Can be a template expression for dynamic binding.
</ParamField>

<ParamField body="min" type="float" default="0">
  Minimum value. The renderer normalizes `(value - min) / (max - min)` to a 0–100 percentage.
</ParamField>

<ParamField body="max" type="float" default="100">
  Maximum value.
</ParamField>

<ParamField body="variant" type="str" default="default">
  Visual variant: `"default"`, `"success"`, `"warning"`, `"destructive"`, `"info"`, `"muted"`.
</ParamField>

<ParamField body="size" type="str" default="default">
  Bar thickness: `"sm"` (4px), `"default"` (6px), `"lg"` (10px).
</ParamField>

<ParamField body="target" type="float | str | None" default="None">
  Target marker position on the bar. Renders a vertical line at this value within the min/max range. Can be a template expression for dynamic binding.
</ParamField>

<ParamField body="indicator_class" type="str | None" default="None">
  Tailwind classes for the indicator fill bar. Overrides variant coloring.
</ParamField>

<ParamField body="target_class" type="str | None" default="None">
  Tailwind classes for the target marker line.
</ParamField>

<ParamField body="orientation" type="str" default="horizontal">
  Layout direction: `"horizontal"` or `"vertical"`.
</ParamField>

<ParamField body="css_class" type="str | None" default="None">
  Tailwind classes for the track (outer container).
</ParamField>
</Card>

## Protocol Reference

```json Progress
{
  "type": "Progress",
  "value?": "number | string",
  "min?": 0,
  "max?": 100,
  "variant?": "default | success | warning | destructive | info | muted",
  "size?": "sm | default | lg",
  "target?": "number | string",
  "indicatorClass?": "string",
  "targetClass?": "string",
  "orientation?": "horizontal | vertical",
  "cssClass?": "string"
}
```

For the complete protocol schema, see [Progress](/protocol/progress).
