Skip to content

Styling & Themes ​

A theme sets the colors shared by the GPU marks and the DOM overlay: background, series palette, gridlines, text, and tooltips. Per-chart options then set series colors, the title, the legend, the grid, padding, and line widths.

Live example

Built-in themes ​

ts
import { Charturbo, CHARTURBO_THEMES } from 'charturbo';

const sdk = await Charturbo.create(canvas);
sdk.setTheme('light');          // 'dark' (default) | 'light'
sdk.getTheme().name;            // 'light'
CHARTURBO_THEMES.dark.palette;  // RgbaTuple[]

Each built-in palette is an 8-color order validated for color-vision deficiency against its own background.

Custom themes ​

Spread an existing theme and override the tokens you need. The GPU color tokens (surface, palette, grid, baseline, crosshair) also accept CSS color strings.

ts
sdk.setTheme('light');
sdk.setTheme({
  ...sdk.getTheme(),
  name: 'brand',
  surface: '#faf6ed',
  palette: ['#3182f6', '#14b8a6', '#f59e0b'],
  textPrimary: '#14213d',
  fontFamily: 'system-ui, sans-serif',
});
sdk.renderBarChart(
  [
    { label: 'A', value: 32, color: '#3182f6' },
    { label: 'B', value: 18, color: '#14b8a6' },
  ],
  { orientation: 'horizontal', cornerRadius: 8, labels: true }
);
sdk.render();

Theme tokens (CharturboTheme):

TokenTypeDescription
namestringTheme name
surfaceRgbaTupleCanvas clear color
paletteRgbaTuple[]Categorical series order
gridRgbaTupleGridlines
baselineRgbaTupleBaseline; default color of line / point annotations
crosshairRgbaTupleCrosshair; default color of band annotations
textPrimarystringTitles, labels
textSecondarystringSecondary text
textMutedstringMuted text
tooltipBackgroundstringTooltip and label pill background
tooltipBorderstringTooltip and label pill border
fontFamilystringFont of the DOM overlay (title, legend, ticks, labels, tooltip)

getTheme() returns GPU tokens as tuples even when they were given as CSS strings.

What setTheme updates ​

setTheme updates the background, text, gridlines, tooltips, annotation default colors, the navigator, and each chart kind's theme-derived styles (pie, heatmap, business, and hierarchy palettes, among others). It emits 'themechange'.

Series and item colors you passed explicitly to a render call are kept. To change those too, call the render*Chart() method again with new options and then render().

The benchmark page switches themes, accent color, palette, font, corner radius, and labels this way. Its Midnight and Paper themes are custom themes from the example; the SDK's built-in string themes are 'light' and 'dark'.

Series colors ​

ts
sdk.renderLineChart([
  { name: 'cpu', values: cpu, color: '#3b82f6' },
  { name: 'mem', values: mem, color: [0.94, 0.35, 0.33, 1] },
  { name: 'net', values: net }, // next palette color
]);

Every color option accepts ColorInput:

  • an [r, g, b, a] tuple in 0..1,
  • '#rgb', '#rgba', '#rrggbb', '#rrggbbaa', rgb() / rgba(), hsl() / hsla(), parsed without the DOM,
  • any other CSS color (named colors and so on), resolved through a 2D canvas when document exists.

An invalid string throws a TypeError. The parser is exported as parseColor.

Title and legend ​

ts
sdk.renderLineChart(series, {
  title: 'Infrastructure telemetry',
  legend: { show: true, toggle: true, emphasize: true, position: 'top', overflow: 'scroll' },
});
sdk.setSeriesVisible(1, false); // same as a legend click
sdk.emphasizeSeries(0);         // fade the other series (null clears)
OptionTypeDefaultDescription
titlestring—Chart title above the plot
legendboolean | ChartLegendOptionsshown with 2+ seriestrue / false or the object below
legend.showbooleantrue with 2+ seriesShow the legend
legend.togglebooleantrueClick toggles series visibility
legend.emphasizebooleantrueHover fades the other series
legend.position'top' | 'bottom' | 'left' | 'right''top'Side of the plot the legend sits on
legend.overflow'scroll' | 'wrap''scroll'Entries that do not fit in one row (top / bottom) or one column (left / right): page them, or wrap into more rows

Legend items are <button aria-pressed> elements, so they work from the keyboard. Toggling emits 'legendtoggle'.

Legend position and paging ​

ts
sdk.renderLineChart(series16, { legend: { position: 'bottom' } });                   // one row, paged
sdk.renderScatterChart(data, { legend: { position: 'right' } });                     // one column, paged
sdk.renderLineChart(series16, { legend: { position: 'top', overflow: 'wrap' } });    // extra rows
  • position: 'top' and 'bottom' add one 28 px row to that side's padding. 'left' and 'right' stack the entries in a column sized to the longest name (72–200 px) and add that width plus an 8 px gap to that side's padding. A side you set in padding keeps your value.
  • overflow: 'scroll' (default): the legend keeps one row or column. Entries are split into pages by their measured sizes, whole entries per page, and ‹ n / m › buttons switch pages. On resize the pages are rebuilt and the page that holds the current first entry stays shown. Entries on other pages get display: none, so they leave the Tab order and image exports.
  • overflow: 'wrap': entries wrap into more rows. Top and bottom legends only (left / right legends always page). Extra rows are not reserved in the padding and may cover the plot.
  • The pager button labels (aria-label) follow the chart locale. See Internationalization.

Live example

Grid ​

ts
sdk.renderLineChart(series, { showBackdropGrid: true, grid: { rows: 4, strokeWidth: 1 } });
sdk.setChartGrid(true, { rows: 4, color: '#e5e7eb' }); // after rendering
OptionTypeDefaultDescription
showBackdropGridbooleantrueHorizontal gridlines and baseline
grid.rowsnumber5Number of horizontal grid intervals
grid.colorColorInputtheme gridGridline color
grid.baselineColorColorInputtheme baselineBaseline color
grid.strokeWidthnumber1Line width in CSS px
verticalGridbooleantrueScatter only: vertical gridlines at the x ticks

Padding ​

ts
sdk.renderLineChart(series, { padding: { right: 24 } });

padding (top, right, bottom, left, CSS px) sets plot margins. Sides you omit are derived from the title, legend, and axes.

Line width ​

ts
sdk.renderLineChart(series, { lineWidth: 2 }); // every series, CSS px (default 2)
sdk.setLineWidth(1.5);    // after rendering: every series
sdk.setLineWidth(4, 0);   // series 0 only

Series lineWidth overrides the chart value. The width stays constant at any zoom. Markers, dashes, and curves are covered in Line.

CSS classes ​

The overlay is plain DOM, so it can be styled with CSS:

ClassElement
.charturbo-sdk-chart-overlayOverlay root above the canvas
.charturbo-sdk-chart-titleTitle
.charturbo-sdk-chart-legend, .charturbo-sdk-legend-itemLegend and its items
.charturbo-sdk-legend-pager, .charturbo-sdk-legend-pageLegend pager and its ‹ › buttons
.charturbo-sdk-axis-tick, .charturbo-sdk-axis-titleTick labels and axis titles
.charturbo-sdk-annotation-labelAnnotation labels
.charturbo-sdk-node-tooltipTooltip

See also ​

MIT License