MetricDefinition
- Status
- Implemented
- Family
- 13 of 13
- Registry
- @lopifi/metric-definition
npx shadcn@latest add @lopifi/theme @lopifi/metric-definitionThe component, rendering
Real data, the shipped component. Switch the theme to check the claims the spec makes below.
The four-layer spec
Every metric card requires one. There is no variant without a definition.
Renders the formula with the actual input values substituted, plus cohort, period, source, and caveat:
Net Revenue Retention 104.6%
────────────────────────────────────────────────────────────────
(Starting MRR + Expansion − Contraction − Churn) ÷ Starting MRR
( 412,000 + 61,400 − 18,200 − 24,100 ) ÷ 412,000
Cohort: customers active on 1 Sep 2026
Period: 1–30 Sep 2026
Source: subscription ledger · excludes one-time fees
Note: new customers excluded by definition
"ARR" means four different things at four companies. This component is why the number in this product is not one of them.
Definitions are versioned. When one changes, historical values computed under the old definition are marked — an unannounced definition change looks like a business change.
Lifted verbatim from Metrics & analysis. The doc and this page are the same paragraphs, so they cannot disagree.
What lands in your repository
One component is never one file. Everything below is copied into your project, where you own it.
- Files
components/ledger/metric-definition.tsx
- npm packages
- @base-ui-components/reactclsxtailwind-merge
- Registry entry
- /r/metric-definition.json
The whole component
No compiled bundle, no black box. This is the file the registry copies, and the file you will edit.
import * as React from "react";
import { cn } from "@/lib/ledger/cn";
import { InfoTip } from "@/components/ledger/info-tip";
import { Rule } from "@/components/ledger/rule";
export interface MetricDefinitionProps extends React.ComponentPropsWithoutRef<"div"> {
cohort: string;
computedUnderOlderDefinition?: boolean;
/** Definitions are versioned; a value computed under an older one says so. */
definitionVersion?: string;
formula: string;
name: string;
/**
* The caveat. It is the longest thing on the card and the least often
* needed, so it rides the ⓘ on the metric name rather than taking three
* lines of the definition list.
*/
note?: string;
period: string;
source: string;
/** The same formula with the actual input values substituted. */
substituted: string;
/** Rendered as given — the caller owns formatting and rounding. */
value: string;
}
/**
* **Every metric card requires one.** There is no variant without a
* definition.
*
* "ARR" means four different things at four companies. This component is why
* the number in this product is not one of them.
*/
export const MetricDefinition = React.forwardRef<HTMLDivElement, MetricDefinitionProps>(
(
{
className,
name,
value,
formula,
substituted,
cohort,
period,
source,
note,
definitionVersion,
computedUnderOlderDefinition = false,
...props
},
ref,
) => (
<div className={cn("rounded-xl border border-border bg-surface p-6", className)} ref={ref} {...props}>
<div className="flex items-baseline justify-between gap-4">
<h3 className="text-title-sm font-medium">
{name}
{note ? (
<InfoTip about={`Caveat on ${name}`} className="text-left" triggerClassName="ml-1.5 align-[-1px]">
{note}
</InfoTip>
) : null}
</h3>
<span className="numeric text-figure-lg font-medium">{value}</span>
</div>
<Rule className="mt-3" variant="subtotal" />
<div className="mt-3 space-y-0.5">
<p className="numeric text-caption text-text-secondary">{formula}</p>
<p className="numeric text-caption text-text-primary">{substituted}</p>
</div>
<dl className="mt-4 space-y-1">
<Row label="Cohort">{cohort}</Row>
<Row label="Period">{period}</Row>
<Row label="Source">{source}</Row>
{definitionVersion ? <Row label="Definition">{definitionVersion}</Row> : null}
</dl>
{computedUnderOlderDefinition ? (
/* The warning is the fact; why it matters is the rationale. One belongs
in the strip, the other one press away. */
<p className="mt-3 flex items-center gap-1.5 rounded-sm bg-warning-subtle px-3 py-2 text-caption text-text-primary">
Computed under an earlier definition
<InfoTip about="Why an earlier definition matters">
An unannounced definition change looks like a business change. Comparing this figure with one
computed under the current definition compares two different metrics.
</InfoTip>
</p>
) : null}
</div>
),
);
MetricDefinition.displayName = "MetricDefinition";
function Row({ label, children }: { label: string; children: React.ReactNode }) {
return (
<div className="flex gap-3">
<dt className="w-20 shrink-0 text-caption text-text-tertiary">{label}</dt>
<dd className="flex-1 text-caption text-text-secondary">{children}</dd>
</div>
);
}
The accounting it encodes
Concepts this component renders. Each one is defined once, in the lexicon, and used identically in the code and the copy.
- ARRARR is a recurring-revenue metric, calculated as MRR × 12.
- MRRMRR is a recurring-revenue metric, calculated as Sum of normalized monthly recurring subscription value.
- Net revenue retentionNet revenue retention is a recurring-revenue metric, calculated as (Starting + Expansion − Contraction − Churn) ÷ Starting.
Also in Metrics & analysis
- NonGaapReconciliationEBITDA below net income, every adjustment named.Spec
- MrrBridgeThe movement, not a single number with a percentage.Spec
- BudgetVsActualPolarity-aware, materiality-filtered, versions tracked.
- ForecastTableProjections dashed and labeled everywhere.
- CovenantMonitorThe contractual definition, not the generic one.Spec
- KpiHealthStripProvisional marking for pre-close numbers.Spec
- RevenueTrackerRevenue by stream, with mix, growth and concentration.
- ExpenseTrackerSpend by category on three bases. Polarity derived per row from the sign convention.
- DriverModelThe inputs a forecast is built from, and what they produce.
- ScenarioCompareScenarios side by side, all measured against the base.
- PlByDimensionThe P&L cut by department, entity or product.
See also
A component is specified in one place, defined in another, and running in a third. All three, from here.
- Metrics & analysis — the family specThe four-layer specification this component was built against, before it was written.Doc
- Financial metric components: definitions and varianceThe family running, with real figures in it, in both themes and at every density.Live
- CatalogAll 179 components, specified before they are written.Doc
- ARRARR is a recurring-revenue metric, calculated as MRR × 12.Term
Elsewhere in the system
Where MetricDefinition sits in the rest of the system — the live section it renders in, the calculators that compute what it displays, and the ledger payloads it is fed from.
- MetricDefinition, runningThe metrics showcase — live, with theme, density, greyscale and reduced-motion switches.Live
- Margin & markupThey are not the same number, and confusing them is how a price list quietly loses money.Tool
- NPV, IRR & XIRRIRR by bisection, so a sign-change-heavy series does not converge on a confident wrong answer.Tool
- Effective vs nominal rate12% compounded monthly is 12.68%. That difference is the covenant you either pass or fail.Tool
- Metrics & analysisMetrics & analysis — specs for 12 React components: MetricDefinition, NonGaapReconciliation, MrrBridge, BudgetVsActual and 8 more.Doc
Components are copied into your repository and meant to be edited — rounding policy, fiscal calendar and compliance copy differ per company.
Told when Metrics & analysis changes
Components are copied into your repo, so a fix here does not reach you on its own. One email when a component in this family changes in a way that needs a migration — and nothing when it does not.