## Pulse KPI (S—007)

A metric card with a sparkline that morphs between ranges, plus pointer and keyboard scrubbing.

- URL: https://sundaeui.dev/components/pulse-kpi
- Category: Cards & data visualization · Art direction: Understated
- Access: Free (no account needed)
- Stack: React 18+, TypeScript, Tailwind CSS; dependencies: none
- Install: `npx shadcn@latest add https://sundaeui.dev/r/pulse-kpi.json`
- Tags: dashboard, tailwind, kpi, chart, animated, sparkline, react

A quiet card for one important number. Switching between 7D, 30D and 90D tweens the curve between shapes instead of redrawing it: each series is resampled to a fixed resolution and interpolated, so the line flows into its new form and the headline value counts to its new total.
Scrub the chart with a pointer, or focus it and use the arrow keys. The headline shows the exact value under the cursor, the delta line becomes the date, and a dotted rule marks the position. The line colour follows whether the change is good, and invert flips the meaning for metrics like churn or latency.
It is plain SVG and Tailwind, with no charting library. The curve uses Catmull-Rom smoothing for a calm, continuous line that never overshoots.

### Usage

```tsx
import { PulseKpi } from '@/components/sundae/pulse-kpi'

<PulseKpi
  label="Net revenue"
  defaultRange="30D"
  series={{ '7D': last7, '30D': last30, '90D': last90 }}   // { date, value }[]
  format={(n) => '$' + (n / 1000).toFixed(1) + 'k'}
/>
```

### Props

- `label` (`string`, required): Metric name.
- `series` (`Record<string, KpiPoint[]>`, required): One series of { date, value } per range. Keys become the range buttons.
- `defaultRange` (`string`): Initially selected range. Defaults to the last key.
- `format` (`(n: number) => string`): Value formatter. Defaults to compact notation.
- `formatDate` (`(d: string) => string`): Date label formatter.
- `invert` (`boolean`): Treat a decrease as positive, for example churn or response time.

### Accessibility

- The card has an aria-label that summarises the value, the change and the range.
- The chart is a focusable role="slider". The arrow keys scrub, and aria-valuetext announces the date and value.
- The range selector is a radio group with visible selected state.
- Colour is never the only signal: the delta chip also uses an arrow direction.
