Liquidity heatmap
FreeResting size by price and time as a heatmap with an optional mid line.
pnpm dlx shadcn@latest add https://caliperui.site/r/liquidity-heatmap.json| Price | 09:30 | 09:45 | 10:00 | 10:15 | 10:30 | 10:45 |
|---|---|---|---|---|---|---|
| 101.00 | 10 | 27 | 44 | 61 | 78 | 95 |
| 100.50 | 41 | 58 | 75 | 92 | 19 | 36 |
| 100.00 | 72 | 89 | 16 | 33 | 50 | 67 |
| 99.50 | 13 | 30 | 47 | 64 | 81 | 98 |
| 99.00 | 44 | 61 | 78 | 95 | 22 | 39 |
When to use #
Use it for
- Seeing how liquidity moved through a session.
- Comparing walls of orders over time.
Skip it when
- A single snapshot; use an order book.
Installation #
terminal
pnpm dlx shadcn@latest add https://caliperui.site/r/liquidity-heatmap.json
Adds its 3 files to components/ui/, each with its own stylesheet, and installs their packages. No account needed. The first part also adds Caliper UI’s tokens; import them once as in Installation.
Usage #
This is the code behind the preview above.
example.tsx
import { LiquidityHeatmap } from "@/components/ui/liquidity-heatmap" export function DepthOverTime() { const times = ["09:30", "09:45", "10:00", "10:15", "10:30", "10:45"]; const prices = [101, 100.5, 100, 99.5, 99]; const values = prices.map((_, row) => times.map((__, column) => 10 + ((row * 31 + column * 17) % 90))); return ( <div className="w-full max-w-xl"> <LiquidityHeatmap label="Resting size by price and time" times={times} prices={prices} values={values} mid={[100.2, 100.1, 100, 100.1, 100.3, 100.2]} unit="lots" /> </div> ); }
API reference #
LiquidityHeatmap
component
PropTypeDefaultDescription
label *string—
times *readonly string[]—One label per column, oldest first.
prices *readonly number[]—One price per row, highest first.
values *readonly (readonly number[])[]—values[row][column]: resting size at that price and time.
midreadonly (number | undefined)[]—Optional mid price per column, drawn as a line.
normalize"all" | "column""all""column" scales each moment by its own densest level.
unitstring""
formatPrice((price: number) => string)(price) => price.toFixed(2)
formatSize((size: number) => string)numberText
loadingboolean—
errorstring—
classNamestring—
Accessibility #
It exposes group and status semantics, with aria-label, aria-busy and aria-hidden kept in step with state. Changes that matter are announced through a live region.
KeyBehaviour
→Moves to the next item or value.
←Moves to the previous item or value.
↑Moves to the previous item or value.
↓Moves to the next item or value.
PageUpMoves by a larger step, or to the previous page.
PageDownMoves by a larger step, or to the next page.
HomeJumps to the first item or the minimum.
EndJumps to the last item or the maximum.
EscapeCloses or cancels, then returns focus to where it came from.
Motion #
It declares no animation in its component source. Any transition comes from its stylesheet, which uses the duration tokens that collapse to instant under prefers-reduced-motion.