Style guide

The living reference for this console. Every example below is static — nothing here fetches data. If a pattern is not on this page, it is not part of the system yet.

Color

Four color languages

  • Dispatchabilitygov-*, only on a labelled lane chip, a map marker or a lane-distribution chart.
  • UI state / severitysignal-*, five steps: critical → warning → caution → positive, plus neutral and info.
  • Health tierhealth, neutral slate, chips only. Never traffic-light colored.
  • Brand / intentprimary (brand, nav-active, links), action (CTAs), destructive (destructive actions only).

A filled labelled chip always means a governance lane. Colored text always means a UI state. The two vocabularies are never mapped onto each other.

Surfaces

bg-surface-0
Page background
bg-surface-1
Panels and cards
bg-surface-2
Panel headers, hover
bg-surface-3
Popovers, tooltips
bg-border-dim
Hairline dividers

Brand and intent

bg-primary
Brand, nav-active, links
bg-action
Calls to action
bg-action-strong
Solid CTA fill (AA)
bg-destructive
Destructive actions

Governance lanes

bg-gov-green
Green lane
bg-gov-orange
Orange lane
bg-gov-red
Red lane
bg-gov-blue
Blue (Clear)
bg-gov-hold
Hold

Health tier (Critical / Degraded / Healthy)

bg-health-critical
Critical
bg-health-degraded
Degraded
bg-health-healthy
Healthy

Signal (UI state)

bg-signal-critical
Critical
bg-signal-warning
Warning
bg-signal-caution
Caution (4th band)
bg-signal-positive
Positive
bg-signal-neutral
Neutral

Confidence

bg-confidence-high
High
bg-confidence-medium
Medium
bg-confidence-low
Low

Charts

bg-chart-1
Series 1
bg-chart-2
Series 2
bg-chart-3
Series 3
bg-chart-4
Series 4
bg-chart-5
Series 5

Typography

text-micro · 10px
Densest legal size in the system
text-mini · 11px
Meta and secondary detail
text-xs · 12px
Dense body and table cells
text-sm · 14px
Default body copy
text-base · 16px
Section heading (h2)
text-lg · 18px
Rarely used
text-xl · 20px
Page title (h1, one per page)
text-eyebrow
Panel title / label
metric hero
1,284
metric inline
12.4%

Type roles

TYPE.panelTitle
Panel header titletext-mini font-semibold uppercase tracking-wider text-foreground
TYPE.sectionHeading
Heading inside a paneltext-mini font-semibold uppercase tracking-wider text-foreground
TYPE.cardTitle
Card / column titletext-sm font-semibold leading-tight text-foreground
TYPE.body
Body copytext-mini text-foreground
TYPE.bodyMuted
Secondary body copytext-mini text-muted-foreground
TYPE.label
Field labeltext-eyebrow
TYPE.status
Inline UI statustext-xs font-medium
TYPE.metric
Inline numeric valuetext-metric text-mini tabular-nums

Spacing and radius

Spacing steps
1
2
3
4
6
8
Control heights
h-8
h-9
h-10
h-11
h-14
Radius
-sm
base
-md
-lg
-full

Elevation

shadow-card
Resting card / panel
shadow-raised
Hover, drag, trigger
shadow-overlay
Popover, tooltip
shadow-modal
Dialog, sheet
shadow-fab
Floating Ask button

Icons

Allowed sizes
size-3size-3.5size-4size-5
In context

Components

Button · default
Button · secondary
Button · outline
Button · ghost
Button · link
Button · destructive
Badge
default
secondary
outline
destructive
Switch
Toggle group
Input
Select
Tabs
Tooltip
Popover
Dialog
TierBadge · lanes
GreenAmberRedClearHoldUnclassified
HealthBadge
HealthyFairDegradedCritical
ActionBadge
DispatchEscalateMonitorInvestigate
ConfidenceBadge
highmediumlow-
DispatchStatusBadge
DispatchWatchDo Not DispatchUnavailable
KPICard
Nodes at risk
1,284
+7.9%vs 1,190 last week
Coverage
94.2%
Skeleton
Panel (nested)

Nested panel

Panel body.
Source unavailable
The upstream token or feed is not currently accessible.
Pending
Data is still being computed for this window.
Partial coverage
Only some sources reported. Values below are incomplete.
No data
Nothing to show for the current filters.
Something went wrong
A request failure, never a measured result.

Do and don't

Don't
className="text-red-500"
Do
className="text-signal-critical"

Palette colors bypass theming. Use a semantic token.

Don't
Node ND-1284
Do
Node ND-1284 Red

A lane is a labelled chip. A colored card edge is not readable as a lane.

Don't
an invented 10.5px size
Do
text-mini

Two named steps replace eight invented micro sizes.

Don't
12.4%
Do
12.4%

One formatting layer keeps every number comparable.

Don't
 
Do
N/A

A blank cell is ambiguous; N/A is an honest absence.

Don't
0
Do
Source unavailable
The upstream token or feed is not currently accessible.

A fabricated 0 reads as a measurement. It never is.

Don't
Accounts: 128
Accounts: 94
Do
Accounts
128
94

Column headers carry the label once, not on every row.

Don't
1284
Do
1,284

Numbers align right in a monospaced metric face; text aligns left.

Don't
Loading…
Do
ND-1284 · −2.1 — refreshing

Keep known data on screen and dim it; never replace it with a spinner.

Don't
Centered
Do
Top-aligned

Card content is top-aligned so scanning down a grid works.

Chips, meters and filters

One chip, one delta, one bar, one segmented control, one filter tile. A page never declares its own — ESLint blocks locally-named *Chip, *Pill, *Tag and *Bar components outside components/shared.

Chip
WeatherReadyPartialUnavailableDense row
DeltaIndicator
+2.4%−1.8%−3.0%0.0%N/A
MetricBar
4931
SegmentedFilter
FilterTile
Don't
Offline
Do
Offline

A filled labelled chip means a governance lane. Everything else is an outlined Chip with a signal tone.

Status vocabulary

Four axes, four looks. A tag never borrows another axis' colour, and colour is never the only carrier of meaning — every tag is labelled.

gov-* is reserved for the governance lane axis. Severity uses signal-*, health uses the health token, and interaction uses brand/action. The design-system audit enforces this: any gov-* colour outside the lane-owning components fails the check.

Governance lane
GreenAmberRedClearHold

Filled gov-* colour. Only lane components paint with governance colour.

Health / severity
HealthyFairDegradedCritical

Outlined signal tones from tone.ts. There is no informational tone: informational state is neutral.

Ticket state
To doAssignedIn progressPaused

Workflow position, not severity — neutral everywhere except Paused, which is a caution. One map, in badges.tsx.

Dispatch decision
Do Not DispatchDispatch recommended

A decision is a signal-toned tag; a call to action is a real button or plain text — never a tag that looks clickable but is not.

Tag sizes
xs — table cellssm — everywhere else

Exactly two sizes, identical padding across every badge. There is no md, and tags never carry a fixed width.

Maps and charts

One map mount. Every map surface renders through ConsoleMap. Pages never call the Maps API directly, so a pin means the same thing everywhere: icons come from the shared marker vocabulary, detail bubbles are React (never HTML strings), pin size is constant, and records without usable coordinates are filtered out and counted in a visible note. Heights use sm | md | lg | fill.

One chart frame. Every recharts consumer renders through ChartFrame: series colors from the chart tokens above, a required accessible name, a stated unit, one legend implementation, and shared loading / error / empty / stale states. An empty series shows a no-data state, never blank axes — blank axes read as zero, which is a different claim.

Reference layouts

When to use which: Dashboard is the landing view for a role or scope — a KPI strip plus a widget grid, nothing more. Detail page is for one entity (a node, a facility, a dispatch) — breadcrumbs, its own KPI strip, and a primary/sidebar split. Table page is for browsing or triaging a collection — toolbar, DataTable, pagination. Map page is for spatial triage — a full-bleed map with an overlay legend and mode toggle. Each archetype below is static and non-fetching; copy the shape, not the literal data.

Widget heights are never hand-set. They derive from the widget’s declared size — the grid column span and row span come from the same table the widget registry reads:

SizeColumn spanRow span
Scol-span-6 sm:col-span-4 lg:col-span-3row-span-2
Mcol-span-12 md:col-span-6row-span-3
Lcol-span-12 md:col-span-6 lg:col-span-8row-span-3
XLcol-span-12 lg:col-span-9row-span-4
Fullcol-span-12row-span-4
3a · Dashboard

Network overview

Role-scoped landing view.

Open faults
128
Dispatchable
42
On hold
9
SLA at risk
6
Resolved today
31
Coverage
97%

Attention queue

Lane distribution

Top facilities

Top nodes

Trajectories

Provenance

3b · Detail page

Node ND-1284

Governance lane
Amber
Health tier
Tier 2
Confidence
High
Data age
4h

Fault history

Metadata

Facility: FAC-0091
Firmware: 4.2.1
Install date: 2022-03-14

Provenance

Model: telemetry-v3
Pipeline: nightly-batch
Latest events for this node.
3c · Table page

Nodes

Filter bar, sortable table, pagination.

4 of 4
  • NodeND-1284
    FacilityFAC-0091
    LaneAmber
    Faults4
  • NodeND-1301
    FacilityFAC-0044
    LaneGreen
    Faults12
  • NodeND-1417
    FacilityFAC-0091
    LaneRed
    Faults1
  • NodeND-1502
    FacilityFAC-0210
    LaneClear
    Faults0
4 rows
Showing 14 of 4 rows
3d · Map page

Node map

Full-bleed map, mode toggle, legend overlay.

Governance lane
GreenAmberRedBlue (Clear)HoldUnclassified
Marker samples
GreenAmberRedBlue (Clear)HoldUnclassified