agentic-ui logoagentic-ui

Meter

Displays a scalar measurement within a known range. Use low / high / optimum thresholds to colour the fill based on whether the value is in an optimal, suboptimal, or critical zone.

Basic

Storage used
x
Memory
x
CPU
x
import { Meter } from "@brijbyte/agentic-ui/meter";
import "@brijbyte/agentic-ui/meter.css";

export default function BasicDemo() {
  return (
    <div style={{ display: "flex", flexDirection: "column", gap: "var(--space-4)", width: "100%" }}>
      <Meter value={24} label="Storage used" showValue format={{ style: "percent", maximumFractionDigits: 0 }} />
      <Meter value={68} label="Memory" showValue />
      <Meter value={91} label="CPU" showValue />
    </div>
  );
}

Thresholds

Battery
x
Battery (low)
x
Battery (critical)
x
CPU load
x
CPU load (elevated)
x
CPU load (critical)
x
Temperature (optimal)
x
Temperature (cold)
x
Temperature (hot)
x
import { Meter } from "@brijbyte/agentic-ui/meter";
import "@brijbyte/agentic-ui/meter.css";

export default function ThresholdsDemo() {
  return (
    <div style={{ display: "flex", flexDirection: "column", gap: "var(--space-4)", width: "100%" }}>
      {/* optimum="high" — higher is better (e.g. battery, signal) */}
      <Meter value={82} low={20} high={60} optimum="high" label="Battery" showValue showTicks />
      <Meter value={38} low={20} high={60} optimum="high" label="Battery (low)" showValue showTicks />
      <Meter value={12} low={20} high={60} optimum="high" label="Battery (critical)" showValue showTicks />

      <div style={{ height: "var(--space-2)", borderTop: "1px solid var(--color-line-subtle)" }} />

      {/* optimum="low" — lower is better (e.g. CPU load, disk usage) */}
      <Meter value={18} low={40} high={75} optimum="low" label="CPU load" showValue showTicks />
      <Meter value={55} low={40} high={75} optimum="low" label="CPU load (elevated)" showValue showTicks />
      <Meter value={88} low={40} high={75} optimum="low" label="CPU load (critical)" showValue showTicks />

      <div style={{ height: "var(--space-2)", borderTop: "1px solid var(--color-line-subtle)" }} />

      {/* optimum="mid" — middle is best (e.g. temperature) */}
      <Meter value={50} low={25} high={75} optimum="mid" label="Temperature (optimal)" showValue showTicks />
      <Meter value={15} low={25} high={75} optimum="mid" label="Temperature (cold)" showValue showTicks />
      <Meter value={88} low={25} high={75} optimum="mid" label="Temperature (hot)" showValue showTicks />
    </div>
  );
}

Sizes

Small
x
Medium
x
Large
x
import { Meter } from "@brijbyte/agentic-ui/meter";
import "@brijbyte/agentic-ui/meter.css";

export default function SizesDemo() {
  return (
    <div style={{ display: "flex", flexDirection: "column", gap: "var(--space-4)", width: "100%" }}>
      <Meter value={60} size="sm" label="Small" showValue />
      <Meter value={60} size="md" label="Medium" showValue />
      <Meter value={60} size="lg" label="Large" showValue />
    </div>
  );
}

Circular gauge

CPU
x
CPU
x
CPU
x
Battery
x
Battery
x
Battery
x
import { CircularMeter } from "@brijbyte/agentic-ui/meter";
import "@brijbyte/agentic-ui/meter.css";

export default function CircularDemo() {
  return (
    <div style={{ display: "flex", alignItems: "center", gap: "var(--space-6)", flexWrap: "wrap" }}>
      {/* Sizes */}
      <CircularMeter size="sm" value={68} showValue label="CPU" />
      <CircularMeter size="md" value={68} showValue label="CPU" />
      <CircularMeter size="lg" value={68} showValue label="CPU" />

      <div style={{ width: 1, height: 80, background: "var(--color-line-subtle)" }} />

      {/* Threshold states */}
      <CircularMeter size="md" value={82} low={20} high={60} optimum="high" showValue label="Battery" />
      <CircularMeter size="md" value={38} low={20} high={60} optimum="high" showValue label="Battery" />
      <CircularMeter size="md" value={12} low={20} high={60} optimum="high" showValue label="Battery" />
    </div>
  );
}

Composed: base-ui Root + styled parts

Disk usage
x
import { Meter as BaseMeter } from "@base-ui/react/meter";
import { MeterTrack, MeterIndicator, MeterLabel, MeterValue } from "@brijbyte/agentic-ui/meter";
import "@brijbyte/agentic-ui/meter.css";

export default function ComposedDemo() {
  return (
    <BaseMeter.Root
      value={73}
      min={0}
      max={100}
      format={{ style: "percent", maximumFractionDigits: 0 }}
      style={{ display: "flex", flexDirection: "column", gap: "var(--space-1-5)", width: "100%" }}
    >
      <div style={{ display: "flex", justifyContent: "space-between" }}>
        <MeterLabel>Disk usage</MeterLabel>
        <MeterValue />
      </div>
      <MeterTrack size="md">
        <MeterIndicator data-meter-state="suboptimal" />
      </MeterTrack>
    </BaseMeter.Root>
  );
}

Composed: circular gauge

CPU
x
Memory
x
Disk
x
import { Meter as BaseMeter } from "@base-ui/react/meter";
import { MeterLabel, MeterValue } from "@brijbyte/agentic-ui/meter";
import "@brijbyte/agentic-ui/meter.css";

// SVG constants
const DIAMETER = 96;
const STROKE_WIDTH = 8;
const RADIUS = (DIAMETER - STROKE_WIDTH) / 2;
const CIRCUMFERENCE = 2 * Math.PI * RADIUS;
const CENTER = DIAMETER / 2;

interface GaugeRingProps {
  value: number;
  min: number;
  max: number;
  color: string;
}

function GaugeRing({ value, min, max, color }: GaugeRingProps) {
  const pct = (Math.min(Math.max(value, min), max) - min) / (max - min);
  const dashOffset = CIRCUMFERENCE * (1 - pct);

  return (
    <svg width={DIAMETER} height={DIAMETER} viewBox={`0 0 ${DIAMETER} ${DIAMETER}`} aria-hidden="true">
      {/* Track */}
      <circle cx={CENTER} cy={CENTER} r={RADIUS} fill="none" strokeWidth={STROKE_WIDTH} stroke="var(--color-surface-3)" />
      {/* Arc */}
      <circle
        cx={CENTER}
        cy={CENTER}
        r={RADIUS}
        fill="none"
        strokeWidth={STROKE_WIDTH}
        strokeDasharray={CIRCUMFERENCE}
        strokeDashoffset={dashOffset}
        strokeLinecap="round"
        stroke={color}
        style={{
          transform: "rotate(-90deg)",
          transformOrigin: "center",
          transition: "stroke-dashoffset 300ms var(--easing-standard, ease)",
        }}
      />
    </svg>
  );
}

const METRICS = [
  { label: "CPU", value: 74, color: "var(--color-accent)" },
  { label: "Memory", value: 51, color: "var(--color-success-solid)" },
  { label: "Disk", value: 88, color: "var(--color-error-solid)" },
];

export default function CircularComposedDemo() {
  return (
    <div style={{ display: "flex", gap: "var(--space-6)", alignItems: "center", flexWrap: "wrap" }}>
      {METRICS.map(({ label, value, color }) => (
        <BaseMeter.Root
          key={label}
          value={value}
          min={0}
          max={100}
          format={{ style: "percent", maximumFractionDigits: 0 }}
          style={{ display: "inline-flex" }}
        >
          <div style={{ position: "relative", width: DIAMETER, height: DIAMETER }}>
            <GaugeRing value={value} min={0} max={100} color={color} />
            <div
              style={{
                position: "absolute",
                inset: 0,
                display: "flex",
                flexDirection: "column",
                alignItems: "center",
                justifyContent: "center",
                gap: 2,
              }}
            >
              <MeterValue
                style={{
                  fontFamily: "var(--font-mono)",
                  fontSize: "var(--font-size-lg)",
                  fontWeight: "var(--font-weight-semibold)",
                  color: "var(--color-primary)",
                  lineHeight: 1,
                }}
              />
              <MeterLabel
                style={{
                  fontFamily: "var(--font-mono)",
                  fontSize: "var(--font-size-xs)",
                  color: "var(--color-secondary)",
                  lineHeight: 1,
                }}
              >
                {label}
              </MeterLabel>
            </div>
          </div>
        </BaseMeter.Root>
      ))}
    </div>
  );
}

API Reference

Displays a scalar measurement within a known range. Use low / high /
optimum thresholds to colour the fill based on whether the value is in
an optimal, suboptimal, or critical zone.

PropTypeDefault
value*number

Current value. Must be between min and max.

minnumber0

Minimum value of the range.

maxnumber100

Maximum value of the range.

lownumber

Upper boundary of the low zone. Values ≤ this are "low".

highnumber

Lower boundary of the high zone. Values ≥ this are "high".

optimum"low" | "mid" | "high"high

Which zone is optimal — determines fill colour:

  • "high" (default) → high=green, mid=amber, low=red (battery, signal)
  • "low" → low=green, mid=amber, high=red (CPU load, disk)
  • "mid" → mid=green, low/high=amber (temperature)
labelReactNode

Accessible + visible label.

showValuebooleanfalse

Show the formatted value next to the label.

formatNumberFormatOptions

Intl.NumberFormatOptions for value formatting.

showTicksbooleanfalse

Show tick marks at low/high threshold positions.

size"sm" | "md" | "lg"md

Bar thickness.

classNamestring

Styled Parts

base-ui docs ↗

Pre-styled wrappers around the corresponding base-ui parts. All base-ui props are forwarded.

CSS Class Names

Available as keys on the MeterStyles object. Each key maps to a hashed CSS module class name at runtime.

circular-centercircular-indicatorcircular-labelcircular-lgcircular-mdcircular-rootcircular-smcircular-svgcircular-trackcircular-valueindicatorlabellabel-rowrootticktracktrack-lgtrack-mdtrack-smvalue