Version 0.3 restructures ChartTheme so every key lives where it semantically belongs. Confusing flat keys like typography.axisFontSize (shared across axes, legend, tooltips) and candlestick.upColor / wickUpColor (direction and part mixed at one level) are gone. Font sizes move into their owning sections; candlestick nests by direction first. Series renderer options (CandlestickSeriesOptions) follow the same restructure so instance overrides stay consistent with the theme.
Other size knobs move into the section they describe:
// 0.2theme.typography.axisFontSize // used by axis ticks, legend, crosshair label, tooltip sub-texttheme.typography.yFontSize // the floating YLabel price badge (misleadingly named)theme.typography.tooltipFontSize // 0.3theme.axis.fontSize // shared default for both axes + legend/crosshair/sparklinetheme.yLabel.fontSizetheme.tooltip.fontSizetheme.typography now contains only { fontFamily, fontSize }. fontSize is the base body-text size (titles, infobar, pie tooltip).
axis.fontSize and axis.textColor are the shared defaults. If an axis needs to diverge, set an override:
axis: { fontSize: 10, textColor: '#787b86', y: { fontSize: 14, textColor: '#d1d4dc' }, // only Y diverges}Two helpers resolve the effective value at read time:
import { resolveAxisFontSize, resolveAxisTextColor } from '@wick-charts/react'; resolveAxisFontSize(theme, 'y'); // 14 (override)resolveAxisFontSize(theme, 'x'); // 10 (shared default)resolveAxisFontSize(theme); // 10 (legend, crosshair, etc.)// 0.2candlestick: { upColor: '#089981', downColor: '#f23645', wickUpColor: '#089981', wickDownColor: '#f23645',} // 0.3candlestick: { up: { body: '#089981', wick: '#089981' }, down: { body: '#f23645', wick: '#f23645' },}Same restructure applies to CandlestickSeriesOptions on <CandlestickSeries options={...}> / addCandlestickSeries({...}):
// 0.2<CandlestickSeries options={{ upColor: '#0f0', wickUpColor: '#000' }} /> // 0.3<CandlestickSeries options={{ up: { body: '#0f0', wick: '#000' } }} />Body shape now says everything:
candlestick: { up: { body: ['#aaff00', '#008800'], wick: '#006600' }, // explicit 2-stop gradient down: { body: '#f23645', wick: '#a01020' }, // flat fill}The old bodyGradient: boolean (and its deprecated alias candleGradient) flag on CandlestickSeriesOptions is removed. In 0.2, bodyGradient: true (default) applied an auto-derived 3-stop lighten/darken gradient to any single-color body. In 0.3, gradient vs. flat is encoded directly in the shape — a string is flat, a tuple is a gradient.
For the old "subtle vertical lift" look, wrap colors in the new autoGradient helper (ships in every framework entrypoint):
import { autoGradient, createTheme } from '@wick-charts/react'; createTheme({ background: '#0f1117', candlestick: { up: { body: autoGradient('#26a69a'), wick: '#26a69a' }, // [lighten, darken] tuple down: { body: autoGradient('#ef5350'), wick: '#ef5350' }, },});All bundled presets (githubLight, monokaiPro, …) already use autoGradient so they look identical to 0.2.
For reading a flat color out of either form (e.g. coloring a legend swatch, an InfoBar value, or a change arrow), use resolveCandlestickBodyColor:
import { resolveCandlestickBodyColor } from '@wick-charts/react'; resolveCandlestickBodyColor(theme.candlestick.up.body); // '#089981' or the top stop of a tuple| Old | New | | --------------------------------------- | ------------------------------------ | | typography.axisFontSize | axis.fontSize | | typography.yFontSize | yLabel.fontSize | | typography.tooltipFontSize | tooltip.fontSize | | candlestick.upColor | candlestick.up.body | | candlestick.downColor | candlestick.down.body | | candlestick.wickUpColor | candlestick.up.wick | | candlestick.wickDownColor | candlestick.down.wick |
Version 0.2 introduces scoped slot / render-prop support on every DOM overlay and cleans up the seriesId prop inconsistencies across them. The runtime surface (ChartContainer, series components, themes, hooks/composables/stores) is unchanged.
Both components were already multi-series by design — passing seriesId narrowed them to one row, which didn't compose well with "show two of five" or "reorder columns" use cases. They now always render every visible series. Filter inside the slot when you need a subset:
// 0.1<Tooltip seriesId="btc" /> // 0.2<Tooltip> {({ snapshots }) => snapshots .filter((s) => s.seriesId === 'btc') .map((s) => ( <div key={s.id}>{s.label}: {s.data.close}</div> )) }</Tooltip>Same shape in Vue (<Tooltip v-slot="{ snapshots }">…</Tooltip>) and Svelte (<Tooltip let:snapshots>…</Tooltip>).
Each snapshot carries { id, seriesId, layerIndex?, label?, color, data }. id is unique (safe for React key / v-for :key / Svelte each-key). seriesId is the owning series (not unique with layered series) — use it for filtering or grouping.
Previously required. Omit the prop on single-series charts and the first compatible visible series is picked automatically:
Existing code that passes seriesId explicitly continues to work unchanged.
Re-exported from every framework package (@wick-charts/react | vue | svelte):
Use distinct cacheKey values when multiple overlays read at once (e.g. 'tooltip', 'infobar-hover') so they don't invalidate each other.
A superset of dataUpdate + seriesChange plus visibility toggles, series-option changes, and setTheme. Custom overlays should subscribe to this single event instead of stacking dataUpdate + seriesChange:
chart.on('overlayChange', rerender);return () => chart.off('overlayChange', rerender);Call chart.getOverlayVersion() for a monotonic number that bumps on every overlayChange.