Volume Chart
Trading volume bars typically paired with price charts. Color-coded by price direction.
Quick Start
import { VolumeChart } from "@chartts/react"
const data = [
{ date: "2024-01-02", open: 170.2, close: 172.1, volume: 48200000 },
{ date: "2024-01-03", open: 172.1, close: 174.9, volume: 52100000 },
{ date: "2024-01-04", open: 174.9, close: 173.5, volume: 39800000 },
{ date: "2024-01-05", open: 173.5, close: 177.6, volume: 61400000 },
{ date: "2024-01-08", open: 177.6, close: 176.2, volume: 44900000 },
{ date: "2024-01-09", open: 176.2, close: 179.8, volume: 57300000 },
]
export function TradingVolume() {
return (
<VolumeChart
data={data}
date="date"
volume="volume"
close="close"
open="open"
className="h-48 w-full"
/>
)
}That renders vertical bars where height corresponds to trading volume and color indicates whether the price moved up or down during that period. Axes, tooltips, and responsive scaling are all automatic.
When to Use Volume Charts
Volume charts show trading activity over time. Volume is a critical secondary indicator in financial analysis, confirming price trends and signaling potential reversals.
Use a volume chart when:
- Displaying trading volume alongside a price chart (candlestick, OHLC, or line)
- Analyzing whether a price move is backed by strong or weak participation
- Spotting unusual volume spikes that may signal news events or institutional activity
- Your audience understands financial data and expects volume as a companion chart
Don't use a volume chart when:
- Your data is not financial in nature (use a bar chart)
- You only have price data without volume (nothing to render)
- Volume is not meaningful for your asset class
- Your audience is non-technical and would be confused by a secondary chart
Props Reference
| Prop | Type | Default | Description |
|---|---|---|---|
data | T[] | required | Array of data objects |
date | keyof T | required | Key for the time axis |
volume | keyof T | required | Key for the volume value |
close | keyof T | required | Key for the closing price (used for directional coloring) |
open | keyof T | required | Key for the opening price (used for directional coloring) |
upColor | string | '#22c55e' | Color for bars where close is above open |
downColor | string | '#ef4444' | Color for bars where close is below open |
barWidth | number | 0.8 | Width of volume bars as a ratio from 0 to 1 |
showMA | boolean | false | Show a moving average line overlaid on the volume bars |
maLength | number | 20 | Number of periods for the moving average calculation |
animate | boolean | true | Enable bar growth animation on mount |
className | string | - | Tailwind classes on the root SVG |
Directional Coloring
Volume bars are colored based on the price direction of their corresponding period. When the close is higher than the open, the bar is green (buying pressure). When the close is lower, the bar is red (selling pressure).
<VolumeChart
data={data}
date="date"
volume="volume"
close="close"
open="open"
upColor="#22c55e"
downColor="#ef4444"
/>This coloring is essential for reading volume in context. A high-volume green bar confirms strong buying interest. A high-volume red bar confirms strong selling pressure.
Custom colors
// Blue/orange scheme
<VolumeChart
data={data}
date="date"
volume="volume"
close="close"
open="open"
upColor="#3b82f6"
downColor="#f97316"
/>
// Muted scheme for dashboards
<VolumeChart
data={data}
date="date"
volume="volume"
close="close"
open="open"
upColor="#86efac"
downColor="#fca5a5"
/>Moving Average Overlay
Enable showMA to render a moving average line on top of the volume bars. This smooths out daily noise and reveals the underlying volume trend.
<VolumeChart
data={data}
date="date"
volume="volume"
close="close"
open="open"
showMA
maLength={20}
className="h-48"
/>The moving average line uses a neutral color (gray) by default so it does not conflict with the up/down coloring of the bars.
Different moving average periods
// Short-term: 10-period MA for active traders
<VolumeChart
data={data}
date="date"
volume="volume"
close="close"
open="open"
showMA
maLength={10}
/>
// Long-term: 50-period MA for trend analysis
<VolumeChart
data={data}
date="date"
volume="volume"
close="close"
open="open"
showMA
maLength={50}
/>When volume is significantly above the moving average, it signals abnormal activity. When volume drops below the average, it suggests declining interest.
Bar Width
The barWidth prop controls how much horizontal space each bar occupies:
// Narrow bars for dense datasets
<VolumeChart
data={yearOfData}
date="date"
volume="volume"
close="close"
open="open"
barWidth={0.5}
/>
// Wide bars for sparse datasets
<VolumeChart
data={weekOfData}
date="date"
volume="volume"
close="close"
open="open"
barWidth={0.95}
/>Standalone vs Paired Usage
Standalone
The VolumeChart works as an independent chart when volume is the primary focus:
<VolumeChart
data={data}
date="date"
volume="volume"
close="close"
open="open"
showMA
className="h-64 w-full"
/>Paired with a price chart
The most common pattern is to stack a VolumeChart below a price chart. Use matching time axes and consistent widths:
<div className="flex flex-col gap-0">
<CandlestickChart
data={data}
x="date"
open="open"
high="high"
low="low"
close="close"
className="h-72 w-full"
/>
<VolumeChart
data={data}
date="date"
volume="volume"
close="close"
open="open"
className="h-24 w-full"
/>
</div>The two charts share the same data array and time axis, so their bars align perfectly. The VolumeChart is typically one-quarter to one-third the height of the price chart.
Accessibility
- Each bar has an
aria-labelwith its date, volume value, and direction (up or down) - The chart has
role="img"with a summary of the date range and volume range - Keyboard navigation: Tab to focus the chart, arrow keys to move between bars
- Screen readers announce each bar's date, volume, and price direction
- Directional coloring is supplemented by ARIA labels so color-blind users still receive direction information
- Animation respects
prefers-reduced-motion
Real-World Examples
Stock volume with moving average
<VolumeChart
data={appleDaily}
date="date"
volume="volume"
close="close"
open="open"
showMA
maLength={20}
upColor="#22c55e"
downColor="#ef4444"
className="h-48 rounded-lg bg-zinc-950 p-3"
/>Crypto exchange volume
const btcVolume = [
{ ts: "2024-01-10", open: 46200, close: 46950, vol: 28400 },
{ ts: "2024-01-11", open: 46950, close: 45800, vol: 35100 },
{ ts: "2024-01-12", open: 45800, close: 47200, vol: 42600 },
{ ts: "2024-01-13", open: 47200, close: 48100, vol: 51200 },
{ ts: "2024-01-14", open: 48100, close: 47500, vol: 38900 },
]
<VolumeChart
data={btcVolume}
date="ts"
volume="vol"
close="close"
open="open"
upColor="#4ade80"
downColor="#fb923c"
showMA
maLength={10}
className="h-40 w-full"
/>Market breadth comparison
<div className="grid grid-cols-3 gap-4">
<div>
<p className="text-sm text-zinc-400 mb-1">NYSE</p>
<VolumeChart
data={nyseData}
date="date"
volume="volume"
close="close"
open="open"
className="h-32"
/>
</div>
<div>
<p className="text-sm text-zinc-400 mb-1">NASDAQ</p>
<VolumeChart
data={nasdaqData}
date="date"
volume="volume"
close="close"
open="open"
className="h-32"
/>
</div>
<div>
<p className="text-sm text-zinc-400 mb-1">S and P 500</p>
<VolumeChart
data={spData}
date="date"
volume="volume"
close="close"
open="open"
className="h-32"
/>
</div>
</div>