# VolumeProfile (/docs/charts/volume-profile)

Activity piled up somewhere in the 140s, and a time axis cannot tell you which level. VolumeProfile is a histogram
turned perpendicular to the usual trend axis: the level runs vertically, and bars extend horizontally by the mass of
activity at each level. The modal level, the point of control or POC, is the only accented mark. The value area (the
levels holding most of the activity) is shaded behind it.

```tsx
import { VolumeProfile } from "@microcharts/react/volume-profile";

const profile = [ { level: 134, weight: 3 }, { level: 136, weight: 6 }, { level: 138, weight: 11 }, { level: 140,
weight: 18 }, { level: 142, weight: 26 }, { level: 144, weight: 20 }, { level: 146, weight: 12 }, { level: 148, weight:
7 }, { level: 150, weight: 4 }, ];

<VolumeProfile data={profile} title="Volume by price" />
```

## Install

```tsx
import { VolumeProfile } from "@microcharts/react/volume-profile";

<VolumeProfile data={profile} title="Volume by price" />
```

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

## Try it

```tsx
import { VolumeProfile } from "@microcharts/react/volume-profile/interactive";

<VolumeProfile
  data={profile}
/>
```

## When to use it

Use it for volume-at-price, level-of-activity distributions, and load by tier. For a time series, or whenever the timing
is what matters, use Sparkline.

## Sizing

**level-activity cell**

```tsx
<VolumeProfile data={profile} label="none" width={32} height={32} />
```

**right side (pair with trend)**

```tsx
<VolumeProfile data={profile} align="right" />
```

## Variants

```tsx
<VolumeProfile
  data={[
    { level: 138, weight: 11 },
    { level: 140, weight: 18 },
    { level: 142, weight: 26 },
    { level: 144, weight: 20 },
    { level: 146, weight: 12 },
  ]}
  align="right"
/>
```

`valueArea` defaults to `0.7`, and the summary states the fraction it used. It is a stated convention, not an implied
confidence interval.

## Edge cases

```tsx
// identical levels collapse into a single bin — the summary refuses to
// claim a concentration and reads "Activity is evenly spread."
<VolumeProfile data={[142, 142, 142, 142]} />
```

```tsx
// no data → no marks, and the accessible name is "No data."
<VolumeProfile data={[]} />
```

## Four homes

**In a sentence**

```tsx
<p>
  Trades at{" "}
  <span className="mc-inline">
    <VolumeProfile data={profile} label="none" width={28} height={28} summary={false} />
  </span>{" "}
  — POC 142.
</p>
```

**In a table cell**

```tsx
<td><VolumeProfile data={profile} label="none" width={32} height={32} /></td>
```

**In a KPI card**

```tsx
<div className="kpi"><span className="figure">142</span><VolumeProfile data={profile} width={80} height={56} /></div>
```

**In a tab header**

```tsx
<button className="tab">AAPL <VolumeProfile data={profile} label="none" width={28} height={28} /></button>
```

Best at KPI/card scale — profile needs a near-square seat.

## Accessibility

The accessible name states where activity concentrates: **"Activity concentrates at 142.33 (POC); 70% within
140.33–145.67."** (the right-aligned demo's 5-level profile, default 12 bins). An even distribution reads **"Activity is
evenly spread."** The interactive entry roves the levels with ↑/↓, announcing each level's activity mass alongside its
share and flagging the POC.

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, press `Escape`, or
press outside the chart. On touch, a tap pins and a drag scrubs.

## Props

| Prop | Type | Description |
| --- | --- | --- |
| `data` (required) | `{ level, weight }[] \| number[]` | Activity mass per level, or raw levels. |
| `valueArea` | `number` | Mass fraction of the shaded value area (0.7). |
| `align` | `"left" \| "right"` | Which way bars grow. |
| `label` | `"poc" \| "none"` | The POC level beside the accent bar. |
| `bins` | `number` | Number of histogram bins (default 12). |
| `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).
