Initial Load Counter

An animated headline number for "how big is the initial payload of this page right now" readings. The value springs to its latest target, an optional budget line renders a verdict-tinted progress bar, and an optional row of shoulder metrics carries warm-cache size, total payload, chunk count, or anything else useful.

Preview
Initial load on /home (cold)184KB
  • Warm cache62 KB
  • Total payload412 KB
  • Chunks14
Customize
Values
184KB
250KB
Options

Installation

npx shadcn@latest add https://craftbits.dev/r/initial-load-counter.json

Usage

import { InitialLoadCounter } from "@craft-bits/core";
 
<InitialLoadCounter
  label="Initial load on /home (cold)"
  bytes={184}
  budget={250}
  unit="KB"
  metrics={[
    { id: "warm", label: "Warm cache", value: "62 KB" },
    { id: "total", label: "Total payload", value: "412 KB" },
    { id: "chunks", label: "Chunks", value: 14 },
  ]}
/>

Drop the budget for a chromeless animated counter:

<InitialLoadCounter bytes={184} unit="KB" label="Initial load" />

Anatomy

  • Headline. Optional label (rendered with the cb-label style) followed by a large monospace number. The number springs to its latest target on prop change.
  • Bar. When budget is set, a thin progress bar renders below the headline. The in-budget fill paints in the verdict tone, the over-budget portion paints critical, and a vertical marker calls out the budget threshold.
  • Metrics. Optional row of shoulder metrics sits under the bar — small labels paired with pre-formatted values.

Understanding the component

  1. Verdict tone. When budget is supplied, a value at or below the budget reads as pass, up to twice the budget reads as warning, and beyond reads as critical. Tones drive the headline color and the bar fill. With no budget, the headline stays on --cb-fg.
  2. Bar scale. maxScale decides where the bar's right edge sits. Defaults to four times the budget when one is set, otherwise one-and-a-half times the current value. Override to share a scale across multiple counters.
  3. Animation. The headline number tweens to its new target via an ease-out curve. Duration defaults to DURATIONS.slow (0.3s) and is overridable via duration. prefers-reduced-motion short-circuits the tween — the number jumps to the new value.
  4. Formatter. format(value) controls how the rounded number renders. Defaults to toLocaleString() — pass your own for SI units, fixed precision, or custom separators.
  5. Metrics shape. Each metric is { id, label, value } and values are already-formatted ReactNode — the widget doesn't impose a unit or formatter on the shoulder row.

Props

PropTypeDefaultDescription
bytesnumberrequiredCurrent measured size.
budgetnumberOptional budget. Enables the bar and verdict.
unitstring'KB'Display unit appended to the headline.
labelReactNode'Initial load'Headline label above the counter.
metricsInitialLoadCounterMetric[]Optional shoulder-metric row.
maxScalenumbercomputedRight edge of the bar, in the same units as bytes.
durationnumber0.3Tween duration in seconds.
format(value) => stringtoLocaleStringNumber formatter.
classNamestringMerged onto the root via cn().

InitialLoadCounterMetric

FieldTypeDescription
idstringStable identifier.
labelReactNodeVisible label.
valueReactNodePre-formatted display value.

Accessibility

  • The wrapper is a <div role="status" aria-live="polite"> so updates to the headline are announced without interrupting the user.
  • data-cb-edu="initial-load-counter" and data-cb-verdict="pass" | "warning" | "critical" are exposed for consumer styling without monkey-patching CSS.
  • The headline carries an aria-label that includes both the current value and the budget when set, so the relationship is conveyed without depending on color.
  • The bar is a role="progressbar" with aria-valuenow driven by the live percentage and aria-valuemin / aria-valuemax clamped to 0 / 100.
  • The animation is short-circuited under prefers-reduced-motion — the number jumps to its new value.

Credits

  • Extracted from: terminal-dreams (src/components/frontend-design/perf-bundle/ui/InitialLoadCounter.tsx). The original was wired to a perf-bundle lesson with fixed cold/warm/total/chunkCount props, a /home (cold) headline string, and a hard-coded 1200 KB bar scale. This rewrite generalises to bytes + optional budget + optional shoulder metrics, makes the unit configurable, and lets consumers control the bar scale.