on GitHub

Metric

A single SQL-driven key figure: a label, a value, and an optional delta. Measured in the browser, so every number is live.

Total flowers
<Metric label="Total flowers" data="db.iris" value="count(*)" />

Format the value

valueFormat takes a d3-format spec, or a function when the spec language can't express it.

Avg petal length
<Metric
  label="Avg petal length"
  data="db.iris"
  value="avg(petal_length)"
  valueFormat="{.2f} cm"
/>

Filters and a delta

filters compose a WHERE before the measure. A delta adds a second figure beneath the value. Positive is a green , negative a red .

Setosa
Virginica
<Columns cols={2}>
  <Metric
    label="Setosa"
    data="db.iris"
    value="count(*)"
    filters={[{ column: "species", operator: "=", value: "setosa" }]}
    delta="12.4"
    deltaFormat="{.1f}% vs last run"
  />
  <Metric
    label="Virginica"
    data="db.iris"
    value="count(*)"
    filters={[{ column: "species", operator: "=", value: "virginica" }]}
    delta="-8.3"
    deltaFormat="{.1f}% vs last run"
  />
</Columns>

The query escape hatch

For what the measure model can't express, pass a full query: its first scalar is the value.

Petal : sepal ratio
<Metric
  label="Petal : sepal ratio"
  query="SELECT avg(petal_length) / avg(sepal_length) FROM db.iris"
  valueFormat="{.2f}"
/>

Props

PropTypeNotes
labelstringPlain text, not interpolated.
datarelationRelation the value is measured from; use query for full SQL.
querystringFull SQL whose first scalar is the value; mutually exclusive with data.
valueSQL exprMeasure over the source, e.g. sum(amount).
filtersFilter[]{ column, operator, value } predicates ANDed into a WHERE.
valueFormatd3-format spec | (v) => stringHow the value renders.
deltameasure | SELECTSecond figure below the value, resolved independently.
deltaFormatd3-format spec | (v) => stringHow the delta renders.
render(ctx) => ReactNodeEscape hatch: draw the value area yourself; label + delta still wrap it.

Expressions in value, query, and filters values support {{binding}} interpolation against the surrounding BindingProvider.

Installation

Metric ships in @n6k.io/ui/components. Nothing to install. Register the namespace once in src/app/mdx-components.tsx and the tag resolves in both .mdx and page.py pages:

import * as n6k from "@n6k.io/ui/components";

export function useMDXComponents(components: MDXComponents): MDXComponents {
  return {
    ...n6k, // Metric, and every other n6k component
    ...components,
  } as unknown as MDXComponents;
}