ChartContainer

import { ChartContainer } from '@wick-charts/react';
 
<ChartContainer theme={catppuccin.theme}>
<LineSeries data={data} />
</ChartContainer>

Top-level React wrapper that creates a ChartInstance and provides it to children via context. Owns the DOM container and canvas lifecycle; renders children as an overlay layer.

Detects <Title>, <InfoBar>, and <Legend> children and positions them as:

  • Title + InfoBar — absolutely-positioned *overlays* stacked at the top of the canvas

block, so the canvas (and therefore the grid) fills the full container height. The stacked height is measured and fed back into chart.setPadding({ top }) so series data stays below them.

  • Legend — flex sibling at the bottom (or right, when position="right"), so its height is

reserved by browser layout.

The root component every chart starts with. Provides theme, axis configuration, padding, and the canvas; collects series and overlays from its children. Use viewport={{ maxVisibleBars, initialRange }} to size the streaming window and apply an initial zoom *before* the first paint (same shape as the imperative chart.setVisibleRange).

Props

children?ReactNode

Series components and UI overlays (Tooltip, TimeAxis, etc.) rendered inside the chart.

theme?ChartTheme

Visual theme. Live — changing this at runtime updates all themed elements.

axis?AxisConfig

Grouped axis configuration (Y/X visibility, bounds, sizing). Live.

padding?default { top: 20, bottom: 20, right: { intervals: 3 }, left: { intervals: 0 } }
{
  top?: number;
  bottom?: number;
  right?: number | {
    intervals: number
  };
  left?: number | {
    intervals: number
  };
}

Viewport padding around the plot area. Live — a later change re-applies via chart.setPadding. Set every side to 0 for an edge-to-edge sparkline.

viewport?
{
  maxVisibleBars?: number;
  initialRange?: VisibleRangeSpec;
}

Viewport-level streaming behavior. Captured at mount only — changing this prop after the chart is created is ignored.

visibleRange?VisibleRangeSpec

Controlled visible range. Same shape as the imperative chart.setVisibleRange — a bar count, an explicit {from, to} window, or {from, bars}. Every reference/value change applies via chart.setVisibleRange, so pair it with onVisibleRangeChange for a two-way binding; a same-value literal (compared structurally) is a no-op, so an inline object from a parent re-render doesn't re-apply.

For a one-shot initial window that isn't re-applied on every prop change, use viewport.initialRange instead.

gradient?default to trueboolean

Show the chart background gradient. Live. Defaults to true.

interactive?default to trueboolean

Enable zoom, pan, and crosshair interactions. Defaults to true.

Mount-only — core has no setInteractive, so changing this prop after mount is ignored.

grid?default { visible: true }{ visible: boolean; }

Background grid configuration. Live. Default: { visible: true }.

headerLayout?'overlay' | 'inline'

How <Title> and <InfoBar> are positioned relative to the canvas. Live.

  • 'overlay' (default): absolute overlays on top of the canvas — the grid

and Y-axis labels render full-height behind the header strip.

  • 'inline': flex siblings above the canvas — the canvas (and grid) are

shifted down by the measured header height, so nothing renders behind the title. The chart background still spans the full container.

animations?boolean | AnimationsConfig

Animation control. true / omitted uses built-in defaults; false disables every category. Per-series options on <LineSeries> / <CandlestickSeries> / <BarSeries> override these chart-level defaults unless the category here is explicitly false.

Init-only, but diffed by value, not reference. A same-value inline object literal is a no-op — only a genuine change to the resolved config recreates the underlying ChartInstance (and its canvas), since the animation engine doesn't support live reconfiguration yet. Still worth a stable reference (useMemo(() => ({...}), [deps])) to avoid the per-render deep-equal check, but forgetting it no longer tears the chart down. In dev mode the container emits a console warning if it detects >3 *genuine* recreates/s.

perf?PerfOption

Runtime performance instrumentation. Off by default — pass a config factory, not a plain object (that pulls the perf module into your bundle only when you actually use it):

  • perfHud() — attach a PerfMonitor and render a visible HUD overlay on this chart.
  • perfHud({ windowMs, maxSamples, ... }) — same, with monitor options.
  • perfHud(existingMonitor) — attach a visible HUD to an already-created monitor.
  • a raw PerfMonitor instance — instrumentation without the HUD.

Only read at mount; changing this prop after the chart is created is ignored.

onEdgeReached?(info: EdgeReachedInfo) => void

Fired after the user releases a pan/zoom gesture that pulled the viewport past a data edge by more than ~10% of the visible range. Hosts typically respond by prefetching more history.

For threshold-based prefetch (load *before* the user fully overshoots), use <EdgeLoader> instead — that component subscribes to viewportChange and arms when the visible range nears the data edge.

Captured at mount only; changing the prop identity later is ignored.

onPointClick?(info: PointClickInfo) => void

Fired on a click (or tap) on the chart canvas that isn't the tail end of a pan drag. info.spatialHit resolves a pie/heatmap/custom-spatial series directly under the pointer; for a time-series series, resolve the point yourself from info.time (chart.getDataAtTime / buildHoverSnapshots). Live — the latest callback is always used.

onPointDoubleClick?(info: PointClickInfo) => void

Fired on a double-click on the chart canvas. The chart also responds by calling fitContent(). Live — the latest callback is always used.

onSeriesHover?(hit: SeriesHoverInfo | null) => void

Fired when the spatially-hovered series/index changes (pie, heatmap, or a custom spatial kind) — null when the pointer leaves every hit area. Live — the latest callback is always used.

onReady?(chart: ChartInstance) => void

Fired once the underlying ChartInstance is constructed — on mount, and again if the chart is ever rebuilt (a genuine animations value change). Use this to reach for imperative APIs the declarative props don't cover yet. Live — the latest callback is always used for the next rebuild.

onVisibleRangeChange?(range: VisibleRange) => void

Fired whenever the committed visible range changes — pan, zoom, fitContent(), a data update that shifts the tail-scroll window, or a visibleRange prop change. Live — the latest callback is always used.

onCrosshairMove?(position: CrosshairPosition | null) => void

Fired on every crosshair move, with null when the pointer leaves the chart. Live — the latest callback is always used.

style?CSSProperties

Inline style for the chart's outer wrapper element. Live.

className?string

Extra class for the chart's outer wrapper element. Live.

Render prop

// <ChartContainer> accepts arbitrary children.