# NetFlow (/docs/charts/net-flow)

NetFlow answers "in versus out — and where does that leave us net?". Inflow is an area above a zero baseline, outflow is
mirrored below it on **one shared magnitude scale** (never independently scaled to balance the picture), and the net
line (`in − out`) rides on top to restore the precise decision value. Gross and net answer different questions; the cell
answers both.

```tsx
<NetFlow
  data={[
    { in: 42, out: 31 },
    { in: 38, out: 35 },
    { in: 45, out: 29 },
    { in: 40, out: 44 },
    { in: 52, out: 38 },
    { in: 48, out: 41 },
    { in: 55, out: 36 },
    { in: 50, out: 47 },
    { in: 58, out: 39 },
    { in: 44, out: 52 },
    { in: 60, out: 41 },
    { in: 57, out: 43 },
  ]}
  format={(n) => `${n}k`}
  label="last"
  title="Monthly cash flow"
  width={260}
  height={30}
/>
```

## Install

```tsx
import { NetFlow } from "@microcharts/react/net-flow";

<NetFlow data={months} title="Monthly cash flow" />
```

Setup (package + stylesheet): [Quickstart](/docs/quickstart#set-up-with-an-ai-agent) or paste [`/agent-setup.md`](/agent-setup.md) into your agent.


## When to use it

- **Good for** — cash flow per account row, in vs out (signups vs churn) in a KPI card, any in-vs-out where the net is
  the decision.
- **Avoid for** — a single net series (Sparkline) or one period's split (Delta / SegmentedBar).


## Variants

```tsx
const months = [
  { in: 45, out: 29 },
  { in: 40, out: 44 },
  { in: 52, out: 38 },
  { in: 44, out: 52 },
  { in: 60, out: 41 },
  { in: 57, out: 43 },
];

<NetFlow data={months} mode="bars" />
<NetFlow data={months} positive="down" />
```

```tsx
<NetFlow
  data={[
    { in: 42000, out: 31000 },
    { in: 38000, out: 35000 },
  ]}
  locale="de-DE"
/>
```

The net label and accessible summary both follow `format`/`locale` — 38000 reads "38.000" under `de-DE` rather than the
English "38,000".

## Edge cases

```tsx
// an area through one point is a lie about continuity — NetFlow forces
// mode="bars" whenever there's only one period, regardless of the mode prop
<NetFlow data={[{ in: 40, out: 25 }]} title="This month" />
```

```tsx
// in/out are magnitudes; a negative reading is invalid data, not a
// direction — it renders as 0, never as flow the other way
<NetFlow data={[{ in: -5, out: -3 }]} title="Bad reading" />
```

A single period always renders as mirrored bars, never an area — an area drawn through one point would imply continuity
the data doesn't have. `in`/`out` are magnitudes: a negative value is invalid input, not a reversed direction, so it's
coerced to `0`. When every period's magnitudes are zero (all periods coerced or genuinely empty), NetFlow draws only the
zero baseline — no areas, no bars, no net line — and the accessible name says so plainly: **"No flow across 1 period."**


## Why this default

Mirrored areas plus a net line, because gross and net answer different questions and a cell must answer both. Both
directions share **one** scale — never independently scaled to make the picture look balanced — and both areas anchor at
zero, so their extents are honest. The net line is a plain `in − out`, never smoothed, and its sign is stated in the
label's **text** so direction is never carried by color alone.

## Accessibility

The accessible name pairs the net with its gross and counts the healthy periods — **"Net +14 last period; in 57 vs out
43; net positive 4 of 6 periods."**. The interactive entry steps the periods and announces inflow, outflow, and the
signed net together.

The interactive entry follows the shared [interaction contract](/docs/accessibility#one-interaction-contract):
arrow keys rove between units on both axes, `Home` and `End` jump to the ends, and a click, tap, `Enter` or
`Space` selects a unit — pinning its readout so it survives blur, until you select it again or press `Escape`.
On touch, a tap pins and a drag scrubs.

## Props

| Prop | Type | Description |
| --- | --- | --- |
| `data` (required) | `{ in; out }[]` | Periods, oldest first — inflow and outflow magnitudes (both ≥ 0). |
| `mode` | `"area" \| "bars"` | Mirrored areas (default) or discrete columns for few periods. |
| `net` | `boolean` | The net line (in − out). Default true. |
| `positive` | `"up" \| "down"` | Which direction is good — 'down' for debt-paydown contexts. |
| `label` | `"last" \| "none"` | Signed net in a right gutter. |
| `animate` | `boolean` | (interactive) Opt-in entrance motion when the chart mounts client-side — add `import "@microcharts/react/motion"` once. Inert on the server, on hydrated server HTML, and under `prefers-reduced-motion`. |

Plus the shared grammar — `data`, `domain`, `color`, `title`, `summary`, `format` — and the layout props (`width`, `height`, `className`, `style`) that every chart accepts. Interactive entries also share `animate` and `live`, and — wherever a chart has more than one navigable unit — `onActive`, `onSelect`, `selectedIndex` and `defaultSelectedIndex`; and — wherever the chart shows a hover value — `readout`. See [the shared grammar](/docs/quickstart#the-shared-grammar).
