jixoai-ui
the terminal design language
loading the style sheet…
Skip to content
docs · print medium: screen

registry:ui · General

statistic — the metric readout

Micro-label over a big tabular-nums value with prefix/suffix snippets and text-glyph trends. The component never guesses what good means for your metric — you compose it.

install — statistic

$npx jixoai-ui add statistic

https://ui.jixoai.com/r/statistic.json

zero-dependency; recipes add press-button + badge

tabular-nums value prefix/suffix snippets text-glyph trends countdown · precision recipes

statistic

statistic — the metric readout: micro-label over a big tabular-nums value, trends as text glyphs.

deploys / week

42 ▲

failed builds

3 ▼

registry items

69

statistic-usage.svelte svelte
<Statistic title="deploys / week" value="42" trend="up" />

usage

Usage

The value is yours — strings or numbers render verbatim; formatting happens before the component.

usage
<Statistic title="deploys / week" value="42" trend="up" />

examples

Examples

Ability-named recipes: the countdown and the affix + precision matrix.

Both recipes compose the public value/snippet surface — the component renders what it is handed, the tick and the digits are page law (a first-class countdown item is the recorded followup).

with countdown

A 90-second deploy window ticking in mm:ss — start it, pause it, reset it. The tabular-nums face keeps every frame the same width, so the digits flip in place without a single layout shift.

deploy window closes in

01:30

idle

statistic-countdown-usage.svelte svelte
<script lang="ts">
  // the countdown, composed: the component renders the value; the tick
  // law is page state (a first-class countdown item is the recorded
  // followup).
  let durationMs = $state(90_000);
  let remainingMs = $state(durationMs);
  let running = $state(false);
  let finished = $state(false);
  let timer;

  function start() {
    if (running) return;
    running = true;
    timer = setInterval(() => {
      remainingMs = Math.max(0, remainingMs - 1_000);
      if (remainingMs === 0) { stop(); finished = true; }
    }, 1_000);
  }
  function stop() {
    running = false;
    clearInterval(timer);
  }
  const mmss = $derived(
    String(Math.floor(remainingMs / 60_000)).padStart(2, '0')
    + ':' + String(Math.floor((remainingMs % 60_000) / 1_000)).padStart(2, '0'));
</script>

<div class="flex items-end gap-4">
  <Statistic title="deploy window closes in" value={mmss} />
  {#if finished}<Badge variant="fill">window closed</Badge>{/if}
</div>
<div class="flex gap-2">
  <PressButton variant="outline" onclick={start} disabled={running || finished}>start</PressButton>
  <PressButton variant="ghost" onclick={stop} disabled={!running}>pause</PressButton>
  <PressButton variant="ghost" onclick={reset}>reset</PressButton>
</div>
<p class="sr-only" aria-live="polite">{finished ? 'window closed' : ''}</p>

with prefix, suffix and precision

One raw number (1234.5) through the affix + precision matrix: the segmented control re-formats the digits live (Intl.NumberFormat), the prefix/suffix snippets carry the glyphs.

revenue / mo

$ 1,234.50 USD

cache hit rate

97.4 %

p95 latency

1,234.50 ms

statistic-affix-usage.svelte svelte
<script lang="ts">
  // formatting is the caller's law: Intl.NumberFormat decides the digits,
  // the prefix/suffix snippets decide the glyphs.
  const raw = 1234.5;
  let digits = $state(2);
  const precise = $derived(new Intl.NumberFormat('en-US',
    { minimumFractionDigits: digits, maximumFractionDigits: digits }).format(raw));
</script>

<!-- prefix/suffix are SNIPPETS: any glyph, any paint -->
<Statistic title="revenue / mo" value={precise}>
  {#snippet prefix()}<span class="text-muted-foreground">$</span>{/snippet}
  {#snippet suffix()}<span class="text-muted-foreground">USD</span>{/snippet}
</Statistic>
<Statistic title="cache hit rate" value="97.4">
  {#snippet suffix()}<span class="text-muted-foreground">%</span>{/snippet}
</Statistic>

types

Metric states

The readout supports neutral metrics, directional trends and composed affixes.

statistic · states

neutral

69

up

42 ▲

down

3 ▼

statistic-states-demo.svelte svelte
<script lang="ts">
  import Statistic from '@ui/statistic.svelte';
</script>

<div class="grid gap-4 sm:grid-cols-3">
  <Statistic title="neutral" value="69" />
  <Statistic title="up" value="42" trend="up" />
  <Statistic title="down" value="3" trend="down" />
</div>

a11y

Accessibility

ARIA

AttributeValueDescription
titlevisible labelNames the metric for every reader.
valuetext contentKeeps formatted values readable and copyable.
aria-live (recipe)polite, one-shotThe countdown announces the CLOSE, never every tick — a ticking live region is noise.

theming

Density and tokens

xs

deploys

42 ▲

default

deploys

42 ▲

lg

deploys

42 ▲

TokenDefaultSource
--jx-stackdensity scaledensity
--jx-gapdensity scaledensity
--jx-textdensity scaledensity
--jx-text-secondarydensity scaledensity
--jx-linedensity scaledensity

axes

Universal props

The eight-axis surface (explicit-props): size · shape · radius · density · color · theme · elevation · motion — each axis takes named steps, auto (inherit the ambient context; stamps nothing), an exact number (px · coefficient · dp · hue per axis), or query() for responsive/container-conditional values. The metric readout is flat content, all no-own; the size axis scales the root and the supply chain is the point. Radius is STAMPED, NEVER CONSUMED (measured, task 111): the readout is flat text with no corner geometry to round — the family reads no --jx-radius-* var (the color-picker #19 class); the demo lane teaches the stamp, the paint stays honest about it.

Statistic · universal props

axes joined

42

named steps

97.4%

statistic-universal.svelte svelte
<Statistic title="axes joined" value="42" size={18} density="small" />

api

Statistic props

Properties

PropertyTypeDefaultDescription
title * string—Metric label.
value * string | number—Displayed metric value (format before it reaches the component).
trend 'up' | 'down'—Optional directional glyph.
prefix Snippet—Content before the value.
suffix Snippet—Content after the value.
class string''Forwarded to the readout root; consumer classes land last.

Universal props

PropertyTypeDefaultDescription
size'small' | 'medium' | 'large' | 'auto' | number'auto' · ambient scopethe base scale — root font-size; parts size in em
shape'round' | 'scoop' | 'bevel' | 'notch' | 'square' | 'squircle' | 'auto''auto' · ambient scopecorner geometry (CSS corner-shape; §14 degrade table)
radius'small' | 'medium' | 'large' | 'auto' | number'auto' · ambient scopecorner size; auto = the concentric broadcast (§3)
density'small' | 'medium' | 'large' | 'auto' | number'auto' · ambient scopespacing/leading scale over the kernel channels (§4)
color'primary' | 'secondary' | 'error' | 'warn' | 'success' | 'info' | 'auto' | number | string'auto' · ambient scopethe hue axis of the fixed oklch primary system (§5)
theme'light' | 'dark' | 'system' | 'auto''auto' · ambient scopelight/dark profile; system = the JS-mutable global (§6)
elevation'level-1' | 'level0' | 'level1' | 'level2' | 'level3' | 'level4' | 'level5' | 'auto' | number'auto' · ambient scopeofficial M3 levels over the surface ladder (§7)
motion'reduced' | 'subtle' | 'normal' | 'expressive' | 'auto' | number'auto' · ambient scopeintensity across the motion kernels (§8)
jixoai-ui ui.jixoai.com the jixoai design language

Theme

Brand hue

0°

Auto cycle · 24h