Bloomberg-y "terminal grid" KPI panel — mono numbers, status tags, sparklines, ▲▼ deltas. The header strip is a tab control: each tab swaps in a separate pane with its own tile set and grid layout (different tile counts allowed). Hover any tile for the detail breakdown.

Key Performance Indicators

LIVE
KPI.01 · 30d WARN
Completion Rate
88.6%
prev 84.2% ▲ 5.2%
KPI.02 · 12mo GOOD
Monthly Revenue
$835K
prev $752K ▲ 11.0%
KPI.03 · 24h GOOD
Server Temp
22.9°C
prev 24.5°C ▼ 6.5%
KPI.04 · 7d WARN
Server Capacity
81.6%
prev 71.0% ▲ 14.9%
KPI.05 · 24h GOOD
Error Rate
0.24%
prev 0.41% ▼ 41.0%
KPI.06 · 12mo NEUTRAL
Tokyo Office
¥11.6M
prev ¥11.2M ▲ 3.5%
KPI.02 · 12mo GOOD
Monthly Revenue
$835K
prev $752K ▲ 11.0%
KPI.06 · 12mo NEUTRAL
Tokyo Office
¥11.6M
prev ¥11.2M ▲ 3.5%
KPI.01 · 30d WARN
Completion Rate
88.6%
prev 84.2% ▲ 5.2%
KPI.03 · 24h GOOD
Server Temp
22.9°C
prev 24.5°C ▼ 6.5%
KPI.04 · 7d WARN
Server Capacity
81.6%
prev 71.0% ▲ 14.9%
KPI.05 · 24h GOOD
Error Rate
0.24%
prev 0.41% ▼ 41.0%

1×3 · .pa-col-1-3 columns

Each tile in its own .pa-col-1-3 (33% page-grid column) as a standalone mini-card — no shared terminal-grid chrome, no tabs. Tests how a single tile renders at one-third of the viewport width, the typical "stat strip" placement.

KPI.01 · 30d WARN
Completion Rate
88.6%
prev 84.2% ▲ 5.2%
KPI.02 · 12mo GOOD
Monthly Revenue
$835K
prev $752K ▲ 11.0%
KPI.06 · 12mo NEUTRAL
Tokyo Office
¥11.6M
prev ¥11.2M ▲ 3.5%

2×3 stack · .pa-col-25 + .pa-col-45 (asymmetric, 30% empty)

Two page-grid columns: 25% wide on the left (narrow stress test), 45% wide on the right (mid-width). Each holds three standalone tiles stacked vertically. The remaining 30% of the row is intentionally empty — this is the "what does my KPI look like in a sidebar widget" test.

KPI.01 · 30d WARN
Completion Rate
88.6%
prev 84.2% ▲ 5.2%
KPI.02 · 12mo GOOD
Monthly Revenue
$835K
prev $752K ▲ 11.0%
KPI.03 · 24h GOOD
Server Temp
22.9°C
prev 24.5°C ▼ 6.5%
KPI.04 · 7d WARN
Server Capacity
81.6%
prev 71.0% ▲ 14.9%
KPI.05 · 24h GOOD
Error Rate
0.24%
prev 0.41% ▼ 41.0%
KPI.06 · 12mo NEUTRAL
Tokyo Office
¥11.6M
prev ¥11.2M ▲ 3.5%

Custom chart library · Chart.js in the chart slot

The terminal sparkline is just a <svg class="pa-kpi-tile__spark"> — swap it for a <canvas class="pa-kpi-tile__spark" data-kpi-chart> and a real charting library renders into the same place, here a Chart.js bar chart so it's clearly not the default line sparkline. The pa-kpi-tile__spark class still carries the tile's sentiment color, so the bars read currentColor and track the sentiment scale + theme.

Key Performance Indicators

LIVE
KPI.01 · 30d WARN
Completion Rate
88.6%
prev 84.2% ▲ 5.2%
KPI.02 · 24h GOOD
Error Rate
0.28%
prev 0.42% ▼ 33.3%

Usage Guide

When to use

Bloomberg-style dense KPI panels: per-tile depth (id, status pill, label, focal value, prev row, sparkline) with an optional tab strip on top that swaps in a different pane (different tile set, different grid layout) per tab. Best for trading floor / NOC / operations dashboards where a single panel must carry several distinct views. If you want even-weight grids with less per-tile chrome, pick Sparkline list or Editorial minimal.

Tab strip (optional)

Each .pa-kpi-terminal can hold a .pa-kpi-terminal__tabs with one or more .pa-kpi-terminal__tab buttons, each carrying a data-tab="…" slug. The body then holds one .pa-kpi-terminal__pane[data-tab="…"] per slug; CSS hides every pane that doesn't have .is-active, and the shared JS toggles .is-active on the clicked tab + matching pane on click. Panes are completely independent — each holds its own __grid, its own modifier, its own tile count. The page's first section shows three tabs with 6 / 2 / 4 tiles respectively, all using the same --2col grid modifier (the n-th-child border suppressors handle the last-row/last-column edges regardless of row count).

Sections without tabs simply omit the __tabs / __pane markup and place a __grid directly in the body — the page's layout-test sections (1×3 and 25/45) and the Chart.js demo do this.

Status pills (different axis from sentiment)

Three pill styles for tile-level status: WARN (filled orange — needs attention), GOOD (text-only — passing, no chrome by design), NEUTRAL (filled grey — informational). Filled-vs-text is a deliberate hierarchy: filled for "act on this", text-only for "this is fine, just confirming".

The pill is on a different axis from the 5-step sentiment scale (very-positive / positive / neutral / negative / very-negative) used on __value and __delta. Sentiment is direction of change (ordinal — "how positive or negative is the movement"). The pill is action urgency (categorical — "does the operator need to do something"). They coexist intentionally: a tile can be --very-negative numerically (big drop) AND --good pill-wise if the drop is expected / on target — and vice versa, a flat-but-bad metric can be --neutral sentiment + --warn pill. Three levels rather than five because the action question is yes/no/maybe, not a five-step gradient.

Color hierarchy via color-mix

The design needs four distinct text levels — focal value, label, secondary unit, dim metadata. Theme tokens (--pa-text-color-2/3/4) didn't give enough contrast spread, so supporting text uses color-mix(in srgb, var(--pa-text-color-1) X%, transparent) with explicit alphas (72% label, 55% unit, 42% id and prev/delta row) and only __num is full --pa-text-color-1. Inverts cleanly in light themes (where --pa-text-color-1 resolves to dark) so the hierarchy survives mode toggling without theme-specific overrides.

--standalone modifier

Tiles inside a .pa-kpi-terminal__grid use grid-bookkeeping borders to share rules with their siblings. A tile placed directly inside a .pa-col-* (no surrounding grid) needs pa-kpi-tile--standalone to draw its own full border + card-bg + bottom margin so it doesn't look orphaned.

Sparkline trailing dot

Same fix as the other showcases: SVG preserveAspectRatio="none" stretches a <circle> into an oval, so JS converts each circle to an HTML <span> inside a .pa-kpi-spark-wrap on init. The dot is sized in CSS pixels so it stays a true circle regardless of chart aspect ratio.

Hover detail popover

Cursor-anchored via Floating UI's computePosition + virtual reference element. Each tile's detail is appended to <body> on init to escape ancestor overflow: hidden; position: fixed + strategy: 'fixed' because cursor coords are viewport-relative; pointer-events: none so the cursor passes through. Tile-anchored placement was tried first but in vertical-stack layouts every tile's "above-it" geometry sat in an identical-looking gap above the next tile, which read as "popover is always at the same spot."


CSS Classes Reference

Card structure

  • pa-kpi-terminal — page-namespace class on .pa-card (or a bare wrapper). Scopes the tab + pane DOM contract so multiple terminals on one page don't cross-fire.
  • pa-kpi-header — flex header with title + controls + LIVE indicator.
  • pa-kpi-terminal__controls — controls group (tabs + LIVE indicator side by side).
  • pa-kpi-live / pa-kpi-live__dot — LIVE pill + animated dot.
  • pa-kpi-terminal__body — card body with internal padding.
  • pa-kpi-terminal__grid — internal tile grid.
  • pa-kpi-terminal__grid--2col — 2-col layout modifier (canonical dense grid).

Tab strip

  • pa-kpi-terminal__tabs — segmented tab container (role="tablist").
  • pa-kpi-terminal__tab — individual tab button. Carries data-tab="<slug>" matching a pane. Add is-active for the selected one.
  • pa-kpi-terminal__pane — pane container. Carries data-tab="<slug>" matching a tab. Hidden by default; add is-active for the visible one.

Tile structure

  • pa-kpi-tile — single tile (used inside .pa-kpi-terminal__grid).
  • pa-kpi-tile--standalone — modifier for tiles placed directly in a .pa-col-* outside a grid (full border + card-bg + bottom margin).
  • pa-kpi-tile--up-strong / --up / --flat / --down / --down-strong — sparkline-direction sentiment modifiers (named by sentiment, not line shape: "error rate dropping" uses --up).

Tile head

  • pa-kpi-tile__head — top row (id + status pill).
  • pa-kpi-tile__id — tile id (e.g. "KPI.01").
  • pa-kpi-tile__status — base status pill.
  • pa-kpi-tile__status--warn — filled orange "needs attention".
  • pa-kpi-tile__status--good — text-only green "passing".
  • pa-kpi-tile__status--neutral — filled grey "informational".
  • pa-kpi-tile__label — uppercase mono caption below the head.

Tile value

  • pa-kpi-tile__values — wrapper for the focal value.
  • pa-kpi-tile__value — focal value element.
  • pa-kpi-tile__num / pa-kpi-tile__unit — numeric + unit spans.
  • pa-kpi-tile__value--very-positive / --positive / --neutral / --negative / --very-negative — coloured-number sentiment modifiers (apply to __num via descendant selector).

Prev row + delta

  • pa-kpi-tile__prev — previous-period row (▲▼ + value, dim).
  • pa-kpi-tile__delta--very-positive / --positive / --neutral / --negative / --very-negative — delta sentiment colours.

Sparkline

  • pa-kpi-tile__spark — chart SVG (or <canvas data-kpi-chart> for library-rendered charts).
  • pa-kpi-spark-wrap — wrapper containing the SVG + the JS-injected dot span.
  • pa-kpi-spark-dot — HTML span replacing the SVG circle (CSS-pixel sized so it stays circular).

Hover detail popover

  • pa-kpi-detail — popover root (moved to <body> on init).
  • pa-kpi-detail__title — uppercase mono header.
  • pa-kpi-detail .pos / .neg / .warn — sentiment-coloured <dd> text.

Framework tokens used by this showcase

  • --pa-very-positive / --pa-positive / --pa-neutral / --pa-negative / --pa-very-negative — 5-step semantic sentiment scale.
  • --pa-warning — orange "off-target / approaching limit" signal.
  • --pa-detail-bg / --pa-detail-text / --pa-detail-row-label / --pa-detail-title / --pa-detail-shadow — popover chrome (intentionally Bloomberg-dark by default; override for theme-aware popovers).
Type / for commands, : to search a category, or just start typing

Settings

Body text size. All elements scale proportionally.
👤

John Doe

Administrator
  • 📊 Dashboard
  • 📝 Forms
  • 📋 Tables
  • 📊 Data Grid