---
title: Threshold Meter
description: A progress bar whose color changes reactively based on value thresholds.
icon: gauge-high
mode: center
---

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

A slider drives a progress bar whose color shifts at each threshold. The slider's reactive reference is forward-declared with a lambda, so it can be used by components above it in the tree — the lambda resolves at render time, after the slider exists.

<ComponentPreview json={{"view":{"cssClass":"gap-6 max-w-sm mx-auto","type":"Column","children":[{"content":"Health Monitor","type":"H3"},{"content":"Drag the slider \u2014 the bar color changes at each threshold.","type":"Muted"},{"cssClass":"gap-4","type":"Column","children":[{"cssClass":"justify-between items-center","type":"Row","children":[{"content":"CPU Usage","type":"Text"},{"cssClass":"font-bold","content":"{{ slider_22 / 100 | percent }}","type":"Text"}]},{"type":"Progress","value":"{{ slider_22 }}","min":0,"max":100,"variant":"default","indicatorClass":"{{ slider_22 < 20 ? 'bg-red-500' : (slider_22 < 60 ? 'bg-primary' : (slider_22 < 75 ? 'bg-amber-500' : 'bg-green-500')) }}"},{"name":"slider_22","type":"Slider","min":0.0,"max":100.0,"value":50.0,"step":1.0,"disabled":false}]}]},"state":{"slider_22":50.0}}} playground=" ">
<CodeGroup>
```python Python icon="python"
from prefab_ui.components import Column, H3, Muted, Progress, Row, Slider, Text
from prefab_ui.rx import Rx

val = Rx(lambda: slider)

with Column(gap=6, css_class="max-w-sm mx-auto"):
    H3("Health Monitor")
    Muted("Drag the slider — the bar color changes at each threshold.")

    with Column(gap=4):
        with Row(css_class="justify-between items-center"):
            Text("CPU Usage")
            Text((val / 100).percent(), bold=True)
        Progress(
            value=val,
            indicator_class=(val < 20).then(
                "bg-red-500",
                (val < 60).then(
                    "bg-primary",
                    (val < 75).then("bg-amber-500", "bg-green-500"),
                ),
            ),
        )
        slider = Slider(min=0, max=100, step=1, value=50)
```
```json Protocol icon="brackets-curly"
{
  "view": {
    "cssClass": "gap-6 max-w-sm mx-auto",
    "type": "Column",
    "children": [
      {"content": "Health Monitor", "type": "H3"},
      {
        "content": "Drag the slider \u2014 the bar color changes at each threshold.",
        "type": "Muted"
      },
      {
        "cssClass": "gap-4",
        "type": "Column",
        "children": [
          {
            "cssClass": "justify-between items-center",
            "type": "Row",
            "children": [
              {"content": "CPU Usage", "type": "Text"},
              {
                "cssClass": "font-bold",
                "content": "{{ slider_22 / 100 | percent }}",
                "type": "Text"
              }
            ]
          },
          {
            "type": "Progress",
            "value": "{{ slider_22 }}",
            "min": 0,
            "max": 100,
            "variant": "default",
            "indicatorClass": "{{ slider_22 < 20 ? 'bg-red-500' : (slider_22 < 60 ? 'bg-primary' : (slider_22 < 75 ? 'bg-amber-500' : 'bg-green-500')) }}"
          },
          {
            "name": "slider_22",
            "type": "Slider",
            "min": 0.0,
            "max": 100.0,
            "value": 50.0,
            "step": 1.0,
            "disabled": false
          }
        ]
      }
    ]
  },
  "state": {"slider_22": 50.0}
}
```
</CodeGroup>
</ComponentPreview>

The `.then()` chains compile to nested ternary expressions in the wire format — `{{ slider_1 < 20 ? 'bg-red-500' : ... }}` — which the renderer re-evaluates on every state change. Because `val = slider.rx` is a reactive reference, any prop that receives it (here `value`, `indicator_class`, and the `Text` content) updates instantly as the slider moves.
