Metric
A Metric shows a labeled headline number with an optional change and trend. Use it for KPI rows and dashboard tiles.
Usage#
import { Metric } from "@clawscale/react";<Metric label="Throughput" value="12,480" unit="rows/s" delta={8.2} />Examples#
Basic#
label names the number and value shows it. Pass the value formatted, with separators and precision.
import { Metric } from "@clawscale/react";
export default function MetricBasic() {
return (
<div style={{ display: "flex", gap: 40 }}>
<Metric label="Active pipelines" value="38" />
<Metric label="Rows ingested today" value="1.84B" />
</div>
);
}Unit and delta#
unit follows the value in muted text. delta adds a Delta below it, a percentage by default. deltaFormat changes the format.
import { Metric } from "@clawscale/react";
export default function MetricUnitDelta() {
return (
<div style={{ display: "flex", gap: 40 }}>
<Metric label="Throughput" value="12,480" unit="rows/s" delta={8.2} />
<Metric label="Cache hit rate" value="94.1" unit="%" delta={-1.2} />
</div>
);
}Good direction#
Set goodDirection="down" when lower is better, as for latency, cost or error rate. A rise then reads as bad.
import { Metric } from "@clawscale/react";
export default function MetricGoodDirection() {
return (
<div style={{ display: "flex", gap: 40 }}>
<Metric label="p95 latency" value="182" unit="ms" delta={3.1} goodDirection="down" />
<Metric label="Error rate" value="0.42" unit="%" delta={-12.5} goodDirection="down" />
</div>
);
}Caption#
caption adds short context next to the delta, usually the comparison period.
import { Metric } from "@clawscale/react";
export default function MetricCaption() {
return (
<div style={{ display: "flex", gap: 40 }}>
<Metric label="Throughput" value="12,480" unit="rows/s" delta={8.2} caption="vs last hour" />
<Metric label="Queued jobs" value="1,204" caption="across 6 regions" />
</div>
);
}Trend#
trend draws a Sparkline under the value, oldest point first. Set trendColor to the chart slot the same series uses elsewhere on the screen.
import { Metric } from "@clawscale/react";
const usEast = [8120, 8340, 8290, 8610, 8580, 8870, 8930, 9050, 9120, 9260, 9310, 9400];
const euWest = [6480, 6420, 6510, 6390, 6300, 6340, 6250, 6220, 6180, 6150, 6120, 6100];
export default function MetricTrend() {
return (
<div style={{ display: "grid", gap: 40, gridTemplateColumns: "repeat(2, 180px)" }}>
<Metric label="Ingest, us-east-1" value="9,400" unit="rows/s" trend={usEast} />
<Metric label="Ingest, eu-west-1" value="6,100" unit="rows/s" trend={euWest} trendColor="var(--cs-chart-2)" />
</div>
);
}Size#
size accepts small, medium (default) and large. It scales the value. The label and footer keep their size.
import { Metric } from "@clawscale/react";
export default function MetricSize() {
return (
<div style={{ display: "flex", gap: 40 }}>
<Metric size="small" label="Small" value="1,204" unit="jobs" />
<Metric size="medium" label="Medium" value="1,204" unit="jobs" />
<Metric size="large" label="Large" value="1,204" unit="jobs" />
</div>
);
}Loading#
loading swaps the value for a skeleton and sets aria-busy. The label stays, so nothing shifts when data arrives. The delta and trend do not turn into skeletons: pass them once you have them.
import { Metric, Switch } from "@clawscale/react";
import { useState } from "react";
export default function MetricLoading() {
const [loading, setLoading] = useState(true);
return (
<div style={{ display: "grid", gap: 16, width: 180 }}>
<Metric label="Throughput" value="12,480" unit="rows/s" loading={loading} />
<Switch label="Loading" checked={loading} onChange={(event) => setLoading(event.currentTarget.checked)} />
</div>
);
}Metric grid#
Put each metric in a compact Card and lay the cards out in a CSS grid. Long labels truncate instead of wrapping.
import { Card, Metric } from "@clawscale/react";
const metrics = [
{ label: "Throughput", value: "12,480", unit: "rows/s", delta: 8.2 },
{ label: "p95 latency", value: "182", unit: "ms", delta: 3.1, goodDirection: "down" },
{ label: "Error rate", value: "0.42", unit: "%", delta: -12.5, goodDirection: "down" },
{ label: "Active pipelines", value: "38", delta: 0 },
{ label: "Rows ingested", value: "1.84B", delta: 4.6 },
{ label: "Compute cost", value: "$1,284", delta: 1.9, goodDirection: "down" },
] as const;
export default function MetricGrid() {
return (
<div style={{ display: "grid", gap: 12, gridTemplateColumns: "repeat(auto-fill, minmax(180px, 1fr))" }}>
{metrics.map((metric) => (
<Card key={metric.label} compact>
<Metric size="small" caption="vs yesterday" {...metric} />
</Card>
))}
</div>
);
}Interactive playground#
Props interface#
Metric also accepts the HTML attributes of a div.
interface MetricProps extends Omit<HTMLAttributes<HTMLDivElement>, "title">@clawscale/react| Props | Description |
|---|---|
caption | ReactNodeShort context under the value, such as "vs last week". |
delta | numberChange since the comparison period. Renders a Delta. |
deltaFormat | DeltaProps["format"]Formats the delta. See Delta. |
goodDirection | DeltaProps["goodDirection"] = "up"Direction that counts as good for the delta. |
labelrequired | ReactNodeWhat the number measures. |
loading | booleanShow a skeleton instead of the value. |
size | "small" | "medium" | "large" = "medium"Visual size. |
trend | readonly number[]Trend data. Renders a Sparkline under the value. |
trendColor | string = "var(--cs-chart-1)"Sparkline color. |
unit | ReactNodeUnit shown after the value, such as "ms" or "GB". |
valuerequired | ReactNodeThe headline value. Pass it formatted. |