Distributed Dashboard

A grid of worker cards for visualising the state of a distributed-training cluster. Each card shows a worker's label, lifecycle status, progress through the current epoch, throughput, and current step. When currentBarrier is supplied, every worker that has reached it is highlighted with the accent ring — the visual stand-in for "these ones cleared the barrier; the slow ones haven't yet". Use it to teach data parallelism, all-reduce cost, and stragglers in synchronous SGD.

Distributed workersbarrier 42 · 02/04
rank 0: waiting, 100% complete. rank 1: waiting, 100% complete. rank 2: computing, 48% complete. rank 3: computing, 35% complete. 2 of 4 workers reached barrier 42.
  • rank 0waiting
    step 0421.2k tok/s
  • rank 1waiting
    step 0421.2k tok/s
  • rank 2computing
    step 0411.1k tok/s
  • rank 3computing
    step 0411.0k tok/s
Customize
Cluster
4
42
State

Installation

npx shadcn@latest add https://craftbits.dev/r/distributed-dashboard.json

Usage

import { DistributedDashboard } from "@craft-bits/core";
 
<DistributedDashboard
  workers={[
    { id: "w0", label: "rank 0", progress: 1, status: "waiting", currentStep: 42 },
    { id: "w1", label: "rank 1", progress: 0.6, status: "computing", currentStep: 41 },
  ]}
  currentBarrier={42}
/>

Stream the worker list from a query — the component is pure, it just renders whatever you give it:

const workers = useWorkerStates();
 
<DistributedDashboard workers={workers} currentBarrier={epoch} />

Switch the throughput unit for inference dashboards:

<DistributedDashboard workers={workers} throughputUnit="req/s" />

Understanding the component

  1. One card per worker. Each card carries the label, a status dot, a progress bar, a step counter, and a throughput readout. Cards lay out in a repeat(auto-fill, minmax(13rem, 1fr)) grid so the dashboard scales from a single worker to thirty-two without changing markup.
  2. Status drives the tone. idle → subtle grey, computing → success, waiting → warning, error → error. The dot and the progress bar share the same tone so the status reads at a glance — colour is only ever a secondary signal alongside the textual badge.
  3. Progress is scaleX, not width. The fill bar uses transform: scaleX(p) with a origin-left anchor so the GPU compositor handles the animation. Animating width would force a layout pass per frame.
  4. Barrier highlight via accent border + ring. Workers whose currentStep === currentBarrier animate to a --cb-accent border + 1px outer ring. Other workers stay on the default border — the contrast carries the "reached vs straggling" story without flashing or pulsing.
  5. SPRINGS.default for everything. The dot, the bar, and the border / ring transition together using the library's default spring, so the whole row settles in one motion. Reduced-motion users get { duration: 0 } and a snap-in render.

Props

PropTypeDefaultDescription
workersreadonly DistributedWorker[]The set of workers to display. Order is preserved.
currentBarriernumberWhen set, workers whose currentStep matches are highlighted with the accent ring.
throughputUnitstring"tok/s"Unit string appended after each worker's throughput readout.
transitionTransitionSPRINGS.defaultSpring used for the dot / bar / border / ring transitions.
classNamestringMerged onto the root <div> via cn().

DistributedWorker

FieldTypeDescription
idstringUnique key — used as the React key and the a11y token.
labelstringHuman-readable card heading.
progressnumberProgress through the current epoch / barrier in [0, 1]. Clamped before render.
throughputnumber?Optional throughput. Pre-formatted with k suffix above 1000.
currentStepnumber?Optional step counter. Compared against currentBarrier for the highlight.
status"idle" | "computing" | "waiting" | "error"?Lifecycle state. Defaults to "idle".

Accessibility

  • The root is role="figure" with aria-labelledby pointing at the visually-hidden "Distributed workers" heading and aria-describedby at an aria-live="polite" summary.
  • The summary narrates each worker's label, status, and percent complete, plus the barrier count when currentBarrier is set.
  • Each progress bar is a role="progressbar" with aria-valuemin, aria-valuemax, aria-valuenow, and an aria-label naming the worker.
  • Status is encoded in three signals — the dot tone, the textual badge ("computing", "waiting", …), and the data-status attribute — so colour is never the only cue.
  • prefers-reduced-motion: reduce short-circuits the spring to { duration: 0 } for the dot, bar, border, and ring — the dashboard renders in its final state with no transitions.

Credits

  • Extracted from: craftingattention (app/src/lessons/primitives/viz/DistributedDashboard.tsx). The original was a four-panel lesson visualisation tightly coupled to runTrainingLoop, a MetricsSnapshot interface, and an internal VizComponentProps contract — loss curves, comm timeline, worker-state pills, and a topology SVG, all driven by an in-component training simulator. Stripped the simulator, the loss/comm/topology panels, the worldSize math, and the runCount autoplay machinery. Generalised the surviving worker-state panel into the public surface: a flat workers array plus an optional currentBarrier highlight, with progress bars rendered via scaleX and the original --color-success-400 / --color-warning-400 ad-hoc palette swapped for --cb-success / --cb-warning semantic tokens.