npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

awesome-kpi-card

v0.1.0

Published

Enterprise-grade KPI Card component for React.

Readme

awesome-kpi-card

Enterprise-grade KPI Card component for React. Three layout variants (compact, detailed, premium), sparkline, trend arrow, variance badge, RAG status indicator, optional REST data fetching with auto-refresh, and full theming via CSS custom properties — all styles injected at runtime so no CSS import is needed.


Features

  • 3 variantscompact (tight, label + value + variance), detailed (sparkline + variance line), premium (sparkline + target + previous + all indicators)
  • Trend arrow — ▲ / ▼ / — based on value vs previous, with a configurable dead-zone (trendSensitivity)
  • Variance badge+4.50% / −3.20% coloured by direction, shown in header (compact) or value row (detailed/premium)
  • RAG status — colour-coded dot + label driven by value / target ratio against configurable thresholds
  • SVG sparkline — polyline chart from history array, with optional animated draw
  • REST data fetchingendpoint prop + autoRefresh polling; local data prop always takes precedence
  • transform hook — normalise any remote payload shape before rendering
  • onClick callback — receives the fully resolved data object
  • 4 built-in themesdark, light, purple plus the default — all driven by CSS custom properties
  • Self-contained — styles injected at runtime; no CSS import, no sub-folder dependencies
  • ESM + CJS dual build — works in Vite, Next.js, CRA, and any modern bundler
  • Zero runtime dependencies beyond React

Installation

npm install awesome-kpi-card
# or
yarn add awesome-kpi-card
# or
pnpm add awesome-kpi-card

Peer dependencies — React ≥ 17 and ReactDOM ≥ 17 must already be installed.


Quick Start

No CSS import needed — styles are injected automatically on first render.

import AwesomeKpiCard from 'awesome-kpi-card';

export default function App() {
  return (
    <AwesomeKpiCard
      variant="premium"
      data={{
        label:    'Revenue',
        value:    5200000,
        target:   5000000,
        previous: 4800000,
        history:  [4000000, 4200000, 4500000, 4800000, 5200000],
      }}
      format="currency"
      currency="USD"
      thresholds={{ good: 1, warning: 0.85 }}
      animated
    />
  );
}

Both import styles work:

// Default import
import AwesomeKpiCard from 'awesome-kpi-card';

Props

| Prop | Type | Default | Description | |---|---|---|---| | variant | 'compact' \| 'detailed' \| 'premium' | 'detailed' | Controls layout, density, and which elements are shown by default. | | label | string | 'KPI Metric' | KPI title label shown in the card header. | | value | number | 0 | Current KPI value. | | target | number | — | Target value. Used for variance, RAG status, and the target line in premium. | | previous | number | — | Previous period value. Used for the trend arrow direction. | | history | number[] | — | Array of historical values for the sparkline (oldest → newest). | | data | object | — | Local data object with any of { label, value, target, previous, history }. Takes precedence over endpoint. | | endpoint | string | — | REST URL to fetch KPI data from. Response root or .data key is used. | | method | string | 'GET' | HTTP method for the endpoint request. | | autoRefresh | number | — | Polling interval in ms. Requires endpoint. | | transform | (normalized, raw) => object | — | Transforms the remote payload before it is merged into the card's data. | | thresholds | { good: number, warning: number } | { good: 1, warning: 0.85 } | RAG ratio thresholds. good = value/target ≥ good, warning = ≥ warning. | | format | 'number' \| 'currency' \| 'percent' | 'number' | Value display format. | | currency | string | 'USD' | ISO currency code for format="currency". | | showSparkline | boolean | variant default | Override sparkline visibility. | | showVariance | boolean | variant default | Override variance badge visibility. | | showTrend | boolean | true | Show/hide the trend arrow. | | showTarget | boolean | variant default | Show the target meta line (on by default in premium). | | showPrevious | boolean | variant default | Show the previous meta line (on by default in premium). | | animated | boolean | false | Animate the sparkline draw on mount. | | trendSensitivity | number | 0 | Dead-zone delta — differences ≤ this value show neutral instead of ▲/▼. | | statusLabels | { good?: string, warning?: string, critical?: string } | — | Override the default RAG status label strings. | | onClick | (data) => void | — | Fired when the card is clicked. Receives the fully resolved data object. | | className | string | — | Additional CSS class on the root <section>. | | style | object | — | Inline styles on the root element. |

Variant defaults

| Feature | compact | detailed | premium | |---|---|---|---| | showSparkline | false | true | true | | showVariance | true | true | true | | showTarget | false | false | true | | showPrevious | false | false | true |


Examples

Example 1 — Three variants side by side

import AwesomeKpiCard from 'awesome-kpi-card';

var kpiData = {
  label:    'Monthly Revenue',
  value:    5200000,
  target:   5000000,
  previous: 4800000,
  history:  [3800000, 4100000, 4400000, 4700000, 4900000, 5200000],
};

var thresholds = { good: 1, warning: 0.9 };

export default function VariantsDemo() {
  return (
    <div style={{ display: 'flex', gap: 20, padding: 32, background: '#10151c', flexWrap: 'wrap' }}>

      <div style={{ width: 260 }}>
        <AwesomeKpiCard
          variant="compact"
          data={kpiData}
          format="currency"
          thresholds={thresholds}
        />
      </div>

      <div style={{ width: 300 }}>
        <AwesomeKpiCard
          variant="detailed"
          data={kpiData}
          format="currency"
          thresholds={thresholds}
          animated
        />
      </div>

      <div style={{ width: 340 }}>
        <AwesomeKpiCard
          variant="premium"
          data={kpiData}
          format="currency"
          thresholds={thresholds}
          animated
        />
      </div>

    </div>
  );
}

Example 2 — Live REST API with auto-refresh and custom status labels

import AwesomeKpiCard from 'awesome-kpi-card';

export default function LiveKpi() {
  return (
    <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 280px)', gap: 20, padding: 32, background: '#0a0f16' }}>

      <AwesomeKpiCard
        variant="premium"
        endpoint="/api/kpi/revenue"
        autoRefresh={30000}
        format="currency"
        currency="USD"
        thresholds={{ good: 1, warning: 0.9 }}
        statusLabels={{ good: 'Exceeding', warning: 'Near Miss', critical: 'Behind' }}
        animated
      />

      <AwesomeKpiCard
        variant="detailed"
        endpoint="/api/kpi/nps"
        autoRefresh={60000}
        format="number"
        thresholds={{ good: 0.9, warning: 0.75 }}
        statusLabels={{ good: 'Excellent', warning: 'Acceptable', critical: 'Poor' }}
      />

      <AwesomeKpiCard
        variant="detailed"
        endpoint="/api/kpi/uptime"
        autoRefresh={10000}
        format="percent"
        thresholds={{ good: 0.999, warning: 0.995 }}
        statusLabels={{ good: 'Healthy', warning: 'Degraded', critical: 'Down' }}
      />

    </div>
  );
}

Example 3 — onClick, transform, and a custom side panel

Demonstrates transforming a non-standard API response and handling card clicks with a detail drawer.

import { useState } from 'react';
import AwesomeKpiCard from 'awesome-kpi-card';

// The API returns: { metric: "...", current: 123, goal: 100, trend: [...] }
// We use `transform` to map it to the expected shape.
function transformApiResponse(normalized) {
  return {
    label:   normalized.metric,
    value:   normalized.current,
    target:  normalized.goal,
    history: normalized.trend,
  };
}

var kpis = [
  { id: 'cac',        label: 'Customer Acq. Cost',  value: 84,      target: 90,      previous: 91,      history: [100, 96, 93, 91, 88, 84],      format: 'currency' },
  { id: 'churn',      label: 'Monthly Churn',        value: 0.021,   target: 0.025,   previous: 0.028,   history: [0.04, 0.035, 0.03, 0.028, 0.025, 0.021], format: 'percent' },
  { id: 'arpu',       label: 'ARPU',                 value: 142,     target: 130,     previous: 128,     history: [110, 118, 124, 128, 135, 142],  format: 'currency' },
  { id: 'activation', label: 'Activation Rate',      value: 0.712,   target: 0.70,    previous: 0.68,    history: [0.61, 0.64, 0.67, 0.68, 0.70, 0.712], format: 'percent' },
];

var drawerStyle = {
  position: 'fixed', top: 0, right: 0, width: 340,
  height: '100vh', background: '#111827',
  borderLeft: '1px solid rgba(255,255,255,0.08)',
  padding: 32, zIndex: 100, color: '#f7f3e8',
  fontFamily: 'sans-serif', overflowY: 'auto',
  display: 'flex', flexDirection: 'column', gap: 16,
};

export default function KpiDashboard() {
  var [selected, setSelected] = useState(null);

  return (
    <div style={{ padding: 32, background: '#0a0f16', minHeight: '100vh' }}>
      <h2 style={{ color: '#f7f3e8', fontFamily: 'sans-serif', marginBottom: 24 }}>Growth Metrics</h2>

      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(260px,1fr))', gap: 20 }}>
        {kpis.map(function(kpi) {
          return (
            <AwesomeKpiCard
              key={kpi.id}
              variant="detailed"
              label={kpi.label}
              value={kpi.value}
              target={kpi.target}
              previous={kpi.previous}
              history={kpi.history}
              format={kpi.format}
              thresholds={{ good: 1, warning: 0.9 }}
              animated
              onClick={function(data) { setSelected({ ...kpi, resolved: data }); }}
            />
          );
        })}
      </div>

      {selected && (
        <div style={drawerStyle}>
          <button
            onClick={function() { setSelected(null); }}
            style={{ alignSelf: 'flex-end', background: 'transparent', border: '1px solid rgba(255,255,255,0.15)', color: '#fff', borderRadius: 4, width: 28, height: 28, cursor: 'pointer' }}
          >✕</button>

          <div style={{ fontSize: 22, fontWeight: 700 }}>{selected.label}</div>
          <div style={{ fontSize: 13, color: 'rgba(247,243,232,0.6)' }}>Format: {selected.format}</div>

          <div style={{ height: 1, background: 'rgba(255,255,255,0.08)' }} />

          <div style={{ display: 'flex', flexDirection: 'column', gap: 8, fontSize: 13 }}>
            <div>Current: <strong>{String(selected.value)}</strong></div>
            <div>Target: <strong>{String(selected.target)}</strong></div>
            <div>Previous: <strong>{String(selected.previous)}</strong></div>
          </div>

          <div style={{ marginTop: 'auto', fontSize: 11, color: 'rgba(255,255,255,0.2)', fontFamily: 'monospace' }}>
            ID: {selected.id}
          </div>
        </div>
      )}
    </div>
  );
}

Theming

All colours are CSS custom properties. Apply a theme class to a wrapper element:

<div class="theme-dark">  <!-- or theme-light / theme-purple -->
  ...
</div>

Or override the variables directly:

:root {
  --kpi-bg:       #0a0f16;
  --kpi-text:     #f7f3e8;
  --kpi-positive: #4cd39b;  /* RAG good / positive variance */
  --kpi-negative: #ff6a6a;  /* RAG critical / negative variance */
  --kpi-warning:  #f1b463;  /* RAG warning */
  --kpi-border:   rgba(255,255,255,0.08);
  --kpi-muted:    rgba(247,243,232,0.7);
  --kpi-panel:    rgba(13,18,26,0.92);
}

The --kpi-accent variable is set automatically per-card to the current RAG colour and drives the card glow.

Built-in theme classes

| Class | Background | Accent | |---|---|---| | (default / dark) | #10151c | #4cd39b / #ff6a6a / #f1b463 | | .theme-light | #f6f6f2 | #1a9b64 / #e15656 / #cf8a3a | | .theme-dark | #0a0f16 | #4cd39b / #ff6a6a / #f1b463 | | .theme-purple | #1a0d2e | #5ee6b8 / #ff7aa2 / #f2c264 |


License

MIT