KPI Number Morph
motiq/kpi-number-morphFreeComponent
An accessible KPI stat that smoothly morphs between values with a direction-aware trend (arrow + sign, never color alone). Controlled value; locale, compact, and currency formatting; loading and error states. Reduced-motion snaps.
Live preview
live · rendered by the registry
Rendered by motiq on their own page — this is the component running, not a screenshot of it.Install it
npx shadcn@latest add https://www.motiq.dev/r/kpi-number-morph.jsonSource
1"use client";23import * as React from "react";45import { cn } from "@/lib/utils";6import { formatNumber, useAnimatedNumber, useReducedMotion } from "@/lib/motiq";78type KpiState = "idle" | "loading" | "error";910export interface KpiNumberMorphProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "prefix"> {11 /** Current metric value (controlled). */12 value: number;13 /** Metric name shown above the number. */14 label?: string;15 prefix?: string;16 suffix?: string;17 /** Fixed decimal places for the morphing number. */18 decimals?: number;19 /** "standard" | "compact" (12.4K, 3.1M). */20 notation?: "standard" | "compact";21 /** ISO currency code — renders the value as currency. */22 currency?: string;23 locale?: string;24 /** Signed change (delta or percent); drives the direction-aware trend row. */25 change?: number;26 /** Text after the change, e.g. "vs last week". */27 changeLabel?: string;28 /** Render the change as a percentage (adds %, one decimal). */29 changeAsPercent?: boolean;30 state?: KpiState;31 durationMs?: number;32}3334function Trend({ dir }: { dir: "up" | "down" }) {35 // Direction is conveyed by the glyph itself (not color alone) and stays36 // visible under forced-colors.37 return (38 <svg width="14" height="14" viewBox="0 0 24 24" fill="none" aria-hidden className="shrink-0">39 {dir === "up" ? (40 <path d="M12 19V5m0 0l-6 6m6-6l6 6" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round" />41 ) : (42 <path d="M12 5v14m0 0l6-6m-6 6l-6-6" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round" />43 )}44 </svg>45 );46}4748/**49 * KpiNumberMorph — an accessible KPI stat that smoothly morphs between values50 * with a clear, direction-aware trend indicator.51 *52 * Accessibility: change direction is carried by an arrow glyph AND a sign in the53 * text — never by color alone; the tile exposes a combined `aria-label`54 * (label + value + change) and does not spam a live region. Loading uses55 * `aria-busy`. Under `prefers-reduced-motion` the number snaps instead of56 * counting. Clean-room original.57 */58export function KpiNumberMorph({59 value,60 label,61 prefix,62 suffix,63 decimals = 0,64 notation = "standard",65 currency,66 locale,67 change,68 changeLabel,69 changeAsPercent = false,70 state = "idle",71 durationMs = 750,72 className,73 ...rest74}: KpiNumberMorphProps) {75 const reduce = useReducedMotion();76 const animate = state === "idle";77// … truncated
What it pulls in
Other registry items
Files it writes
More from motiq
All 100 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Activity Streamactivity-stream | motiq | Components | Free | 1 dep | |
| Adaptive Safe-Zone Gridadaptive-safe-zone-grid | motiq | Components | Free | no deps | |
| Agent Run Timelineagent-run-timeline | motiq | Components | Free | 1 dep | |
| AI Response Streamai-response-stream | motiq | Components | Free | 1 dep | |
| Animated Accordionanimated-accordion | motiq | Components | Free | 2 deps | |
| Animated Buttonanimated-button | motiq | Components | Free | 1 dep | |
| Animated Dialoganimated-dialog | motiq | Components | Free | 2 deps | |
| Animated Gridanimated-grid | motiq | Components | Free | 2 deps |
