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
- Current
- 88.6%
- Previous
- 84.2%
- Δ absolute
- +4.4pp
- Δ percent
- +5.2%
- Target
- 90.0%
- Current
- $835K
- Previous
- $752K
- Δ absolute
- +$83K
- Δ percent
- +11.0%
- Target
- $900K
- Current
- 22.9°C
- Previous
- 24.5°C
- Δ absolute
- −1.6°C
- Δ percent
- −6.5%
- Target
- ≤ 23°C
- Current
- 81.6%
- Previous
- 71.0%
- Δ absolute
- +10.6pp
- Δ percent
- +14.9%
- Target
- ≤ 75%
- Current
- 0.24%
- Previous
- 0.41%
- Δ absolute
- −0.17pp
- Δ percent
- −41.0%
- Target
- ≤ 0.50%
- Current
- ¥11.6M
- Previous
- ¥11.2M
- Δ absolute
- +0.39M
- Δ percent
- +3.5%
- Target
- ¥13.0M
- Current
- $835K
- Previous
- $752K
- Δ absolute
- +$83K
- Δ percent
- +11.0%
- Target
- $900K
- Current
- ¥11.6M
- Previous
- ¥11.2M
- Δ absolute
- +0.39M
- Δ percent
- +3.5%
- Target
- ¥13.0M
- Current
- 88.6%
- Previous
- 84.2%
- Δ absolute
- +4.4pp
- Δ percent
- +5.2%
- Target
- 90.0%
- Current
- 22.9°C
- Previous
- 24.5°C
- Δ absolute
- −1.6°C
- Δ percent
- −6.5%
- Target
- ≤ 23°C
- Current
- 81.6%
- Previous
- 71.0%
- Δ absolute
- +10.6pp
- Δ percent
- +14.9%
- Target
- ≤ 75%
- Current
- 0.24%
- Previous
- 0.41%
- Δ absolute
- −0.17pp
- Δ percent
- −41.0%
- Target
- ≤ 0.50%
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.
- Current
- 88.6%
- Previous
- 84.2%
- Δ absolute
- +4.4pp
- Δ percent
- +5.2%
- Target
- 90.0%
- Current
- $835K
- Previous
- $752K
- Δ absolute
- +$83K
- Δ percent
- +11.0%
- Target
- $900K
- Current
- ¥11.6M
- Previous
- ¥11.2M
- Δ absolute
- +0.39M
- Δ percent
- +3.5%
- Target
- ¥13.0M
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.
- Current
- 88.6%
- Previous
- 84.2%
- Δ absolute
- +4.4pp
- Δ percent
- +5.2%
- Target
- 90.0%
- Current
- $835K
- Previous
- $752K
- Δ absolute
- +$83K
- Δ percent
- +11.0%
- Target
- $900K
- Current
- 22.9°C
- Previous
- 24.5°C
- Δ absolute
- −1.6°C
- Δ percent
- −6.5%
- Target
- ≤ 23°C
- Current
- 81.6%
- Previous
- 71.0%
- Δ absolute
- +10.6pp
- Δ percent
- +14.9%
- Target
- ≤ 75%
- Current
- 0.24%
- Previous
- 0.41%
- Δ absolute
- −0.17pp
- Δ percent
- −41.0%
- Target
- ≤ 0.50%
- Current
- ¥11.6M
- Previous
- ¥11.2M
- Δ absolute
- +0.39M
- Δ percent
- +3.5%
- Target
- ¥13.0M
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
- Current
- 88.6%
- Previous
- 84.2%
- Δ percent
- +5.2%
- Target
- 90.0%
- Current
- 0.28%
- Previous
- 0.42%
- Δ percent
- −33.3%
- Target
- ≤ 0.50%
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. Carriesdata-tab="<slug>"matching a pane. Addis-activefor the selected one.pa-kpi-terminal__pane— pane container. Carriesdata-tab="<slug>"matching a tab. Hidden by default; addis-activefor 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__numvia 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).