Skip to main content

Styling and Themes

Every colour SciTrader draws with comes from one theme: an ISciTraderTheme object. One theme styles the chart, its candles and indicators, the drawings, the market depth ladder, and every toolbar and control around them, so they always match.

SciTrader's three built-in themes, Dark, Light and Ocean, on a candlestick chart with an order book heatmap, RSI and a market depth ladder

SciTrader's three built-in themes, Dark, Light and Ocean, on a candlestick chart with an order book heatmap, RSI and a market depth ladder

The Three Built-In Themes​

ThemeConstantKey in SCITRADER_THEMESLook
DarkSCITRADER_DARK_THEMEdarkSciTrader's dark purple-grey. Charts use it unless given another
LightSCITRADER_LIGHT_THEMElightA white chart, with darker, more saturated candles and indicators
OceanSCITRADER_OCEAN_THEMEoceanDeep navy, with sky-blue accents and teal and coral candles

SCITRADER_THEME_LIST lists all three, in that order, e.g. for a theme picker. To make your own, see Creating a Custom Theme.

TypeScript Example: Switching Between the Three Themes​

BTC-USD from Coinbase with SMA, RSI and MACD. The buttons switch between the three built-in themes with setTheme, and write the theme’s CSS variables on the page, so the toolbar follows too.

The code for this example is found below.

import "scichart-scitrader/scitrader.css";
import {
applyThemeCssVariables,
CandleInterval,
CoinbaseExchange,
defaultExchangeProvider,
idbPriceStore,
ISciTraderTheme,
MACDStudy,
OHLCStudy,
RSIStudy,
SciFinanceChartPanel,
SCITRADER_DARK_THEME,
SCITRADER_THEME_LIST,
SMAStudy,
themeDisplayName,
VolumeStudy,
} from "scichart-scitrader";

// This example expects this HTML:
// <div style="display: flex; flex-direction: column; height: 100%">
// <div id="toolbar"></div>
// <div id="chart" style="flex: 1; min-height: 0"></div>
// </div>

// Register a data source, once, at app startup
defaultExchangeProvider.registerExchange(CoinbaseExchange, idbPriceStore);

async function createChart() {
// 1. Create the chart with a theme. Leave `theme` out for SCITRADER_DARK_THEME
const financeChartPanel = await SciFinanceChartPanel.create(document.getElementById("chart"), {
exchangeName: CoinbaseExchange.name, // name="Coinbase" matches the built-in CoinbaseExchange
symbol: "BTC-USD",
interval: CandleInterval.SIX_HOURS,
period: "3M",
theme: SCITRADER_DARK_THEME,
studies: [new OHLCStudy(), new VolumeStudy(), new SMAStudy({ length: 20 }), new RSIStudy(), new MACDStudy()],
});
const chart = financeChartPanel.financeApi;

// 2. Switch theme. setTheme restyles the live chart in place: backgrounds, axes, candles,
// studies, legend, crosshair and the pane controls
function applyTheme(theme: ISciTraderTheme) {
chart.setTheme(theme);
// HTML outside the chart, like this toolbar, reads the theme from CSS variables
// (--st-ui-text, --st-ui-accent, …): write them on a parent of it
applyThemeCssVariables(document.body, theme);
renderToolbar(theme);
}

// The three built-in themes: Dark, Light and Ocean
function renderToolbar(current: ISciTraderTheme) {
const toolbar = document.getElementById("toolbar");
Object.assign(toolbar.style, toolbarStyle);
toolbar.replaceChildren(
...SCITRADER_THEME_LIST.map((theme) => {
const button = document.createElement("button");
button.textContent = themeDisplayName(theme); // the name without "SciTrader "
Object.assign(button.style, buttonStyle(theme === current));
button.onclick = () => applyTheme(theme);
return button;
})
);
}

applyTheme(SCITRADER_DARK_THEME);

// When the page goes away: financeChartPanel.cleanup();
return financeChartPanel;
}

// The toolbar's colours are the theme's CSS variables, so it follows the theme too
const toolbarStyle: Partial<CSSStyleDeclaration> = {
display: "flex",
gap: "4px",
padding: "8px 12px",
background: "var(--st-ui-toolbar-background)",
borderBottom: "1px solid var(--st-ui-divider)",
};

const buttonStyle = (selected: boolean): Partial<CSSStyleDeclaration> => ({
padding: "4px 14px",
border: "1px solid var(--st-ui-divider)",
borderRadius: "4px",
background: selected ? "var(--st-ui-accent)" : "var(--st-ui-button-background)",
color: selected ? "#ffffff" : "var(--st-ui-toolbar-text)",
font: "13px var(--st-font-family, sans-serif)",
cursor: "pointer",
});

createChart();

React Example: Switching Between the Three Themes​

The same in React. SciTraderThemeProvider holds the theme for the toolbar, and the picker uses useSciTraderThemeSwitch. The chart takes the theme through setTheme.

The code for this example is found below.

import "scichart-scitrader/scitrader.css";
import * as React from "react";
import {
CandleInterval,
CoinbaseExchange,
defaultExchangeProvider,
idbPriceStore,
ISciFinanceChartPanelApi,
ISciFinanceChartPanelConfig,
ISciTraderTheme,
MACDStudy,
OHLCStudy,
RSIStudy,
SCITRADER_DARK_THEME,
SMAStudy,
themeDisplayName,
VolumeStudy,
} from "scichart-scitrader";
import {
SciFinanceChartView,
SciTraderThemeProvider,
useSciTraderTheme,
useSciTraderThemeSwitch,
} from "scichart-scitrader-react";

// Register a data source, once, at app startup
defaultExchangeProvider.registerExchange(CoinbaseExchange, idbPriceStore);

export function ThemedChart() {
// 1. Your app holds the theme. SciTraderThemeProvider writes it as CSS variables for the HTML
// components, and onThemeChange lets a theme picker inside it change it
const [theme, setTheme] = React.useState<ISciTraderTheme>(SCITRADER_DARK_THEME);

return (
<SciTraderThemeProvider theme={theme} onThemeChange={setTheme}>
<div style={{ display: "flex", flexDirection: "column", height: "100%" }}>
<ThemePicker />
<Chart />
</div>
</SciTraderThemeProvider>
);
}

// 2. A theme picker: useSciTraderThemeSwitch gives the current theme, the themes on offer (the
// three built-in ones unless you pass `themes`) and setTheme
function ThemePicker() {
const themeSwitch = useSciTraderThemeSwitch();
if (!themeSwitch) return null; // no onThemeChange on the provider
return (
<div style={toolbarStyle}>
{themeSwitch.themes.map((theme) => (
<button
key={theme.name}
style={buttonStyle(theme === themeSwitch.theme)}
onClick={() => themeSwitch.setTheme(theme)}
>
{themeDisplayName(theme)}
</button>
))}
</div>
);
}

function Chart() {
// 3. The chart is drawn by WebGL, which can't read CSS variables, so it takes the theme
// itself: in `config` when it is created, then through setTheme
const theme = useSciTraderTheme();
const [api, setApi] = React.useState<ISciFinanceChartPanelApi>();
React.useEffect(() => api?.financeApi.setTheme(theme), [api, theme]);

// Create the config once per mounted chart: studies are live objects bound to one chart
const config = React.useMemo<ISciFinanceChartPanelConfig>(
() => ({
exchangeName: CoinbaseExchange.name, // name="Coinbase" matches the built-in CoinbaseExchange
symbol: "BTC-USD",
interval: CandleInterval.SIX_HOURS,
period: "3M",
theme,
studies: [new OHLCStudy(), new VolumeStudy(), new SMAStudy({ length: 20 }), new RSIStudy(), new MACDStudy()],
}),
// eslint-disable-next-line react-hooks/exhaustive-deps
[]
);

return (
<div style={{ flex: 1, minHeight: 0 }}>
<SciFinanceChartView config={config} onInit={setApi} />
</div>
);
}

// The toolbar's colours are the theme's CSS variables, so it follows the theme too
const toolbarStyle: React.CSSProperties = {
display: "flex",
gap: 4,
padding: "8px 12px",
background: "var(--st-ui-toolbar-background)",
borderBottom: "1px solid var(--st-ui-divider)",
};

const buttonStyle = (selected: boolean): React.CSSProperties => ({
padding: "4px 14px",
border: "1px solid var(--st-ui-divider)",
borderRadius: 4,
background: selected ? "var(--st-ui-accent)" : "var(--st-ui-button-background)",
color: selected ? "#ffffff" : "var(--st-ui-toolbar-text)",
font: "13px var(--st-font-family, sans-serif)",
cursor: "pointer",
});

Applying a Theme​

Give the chart a theme when you create it:

import { SCITRADER_LIGHT_THEME, SciFinanceChartPanel } from "scichart-scitrader";

const financeChartPanel = await SciFinanceChartPanel.create(element, { /* … */ theme: SCITRADER_LIGHT_THEME });

Each part of the SDK takes the theme in the way it is drawn:

PartDrawn withHow it gets the theme
The chart: candles, indicators, axes, legend, crosshairWebGLconfig.theme, then financeApi.setTheme(theme)
The chart's own controls: pane control bars, dividers, loading statesHTMLFrom the chart, which writes the theme's CSS variables on its container
The market depth ladderCanvasMarketDepthPanel's theme option, then setTheme(theme). MarketDepthView follows the React provider
Toolbars and other controls outside the chartHTML, styled by the stylesheetThe theme's CSS variables on an element above them: applyThemeCssVariables(element, theme), or SciTraderThemeProvider in React

So for one theme everywhere, give it to each: the example above does this for the chart and its toolbar.

Switching Theme​

financeChartPanel.financeApi.setTheme(SCITRADER_OCEAN_THEME);
applyThemeCssVariables(document.body, SCITRADER_OCEAN_THEME); // toolbars outside the chart

setTheme restyles a live chart in place, with no reload: backgrounds, axes, candles, every study, the legend, the crosshair, the current-price line and the pane controls. themeChanged fires afterwards, and studies added later use the new theme.

What a theme switch leaves alone. A colour or style someone chose keeps its value:

  • axis options passed in axisDefaults, or to applyAxisStyle;
  • a background set by surfaceConfig;
  • colours passed to a study's constructor, such as new SMAStudy({ renderOptions: { stroke: "#F59E0B" } });
  • colours the user edited in a study's settings form.

It works by comparing values: a colour that still equals the old theme's value follows the theme, and any other colour stays. "Reset to defaults" in a study form resets to the current theme's colours.

Themes in React: SciTraderThemeProvider​

Wrap the React components in SciTraderThemeProvider, and give the chart the same theme:

import { SciFinanceChartView, SciTraderThemeProvider } from "scichart-scitrader-react";

<SciTraderThemeProvider theme={theme}>
<SciFinanceChartView config={{ /* … */ theme }} onInit={setApi} />
<MarketDepthView source={source} symbol="BTC-USD" />
</SciTraderThemeProvider>

// The chart is drawn by WebGL, which can't read CSS, so it takes later changes through setTheme
React.useEffect(() => api?.financeApi.setTheme(theme), [api, theme]);
  • The provider writes the theme as CSS variables on a wrapper element (display: contents), and on :root, so menus and pickers attached to <body> follow it too. Set global={false} on a nested provider that should theme only its own part of the page. It is safe to render on the server.
  • Changing theme restyles every component at once, without a remount.
  • useSciTraderTheme() gives the theme to components that need a colour in code.
  • A theme picker: give the provider onThemeChange (and themes, which defaults to the three built-in ones). Inside it, useSciTraderThemeSwitch() returns the current theme, the themes on offer and setTheme, as the example's picker uses.

With MUI. The SDK doesn't use MUI. If your app does, build its MUI theme from the same ISciTraderTheme, mapping the background, paper, text, accent and light or dark mode, so both match.

SciTraderThemeProvider, useSciTraderTheme and useSciTraderThemeSwitch, with their TSDoc
interface ISciTraderThemeProviderProps {
theme?: ISciTraderTheme;
/** Extra styles for the wrapper element. It uses `display: contents` by default, so it takes no space in the layout. */
style?: React.CSSProperties;
className?: string;
/**
* Also publish the theme's variables on `:root`. Default `true`. Needed by anything rendered
* outside this element in the DOM: menus, pickers and dialogs attached to `<body>`, such as
* the SDK's candle-type menu and colour picker, or an app's MUI dialogs.
* Set `false` on a nested provider that should theme only its own subtree.
*/
global?: boolean;
/**
* Makes the theme switchable from inside: a theme picker built with `useSciTraderThemeSwitch`
* calls this with the theme picked. The host owns the state: store the new theme and pass it
* back as `theme`. Without it, `useSciTraderThemeSwitch` returns `undefined`.
*/
onThemeChange?: (theme: ISciTraderTheme) => void;
/** The themes a theme control offers, when {@link onThemeChange} is set. Default: the built-in themes. */
themes?: readonly ISciTraderTheme[];
children?: React.ReactNode;
}

interface ISciTraderThemeSwitch {
theme: ISciTraderTheme;
themes: readonly ISciTraderTheme[];
setTheme: (theme: ISciTraderTheme) => void;
}

/** Makes a SciTrader theme available to the React components inside it. */
function SciTraderThemeProvider(props: ISciTraderThemeProviderProps): JSX.Element;
/** The theme from the nearest provider, or the dark theme outside one. */
function useSciTraderTheme(): ISciTraderTheme;
/** The current theme, the themes on offer and setTheme; `undefined` under a provider without onThemeChange. */
function useSciTraderThemeSwitch(): ISciTraderThemeSwitch | undefined;

Remembering the User's Theme​

Store a theme's id, not the object, and look it up when the page loads:

import { builtInThemeId, SCITRADER_DARK_THEME, SCITRADER_THEMES } from "scichart-scitrader";

localStorage.setItem("theme", builtInThemeId(theme)); // "dark", "light" or "ocean"

const saved = SCITRADER_THEMES[localStorage.getItem("theme") as keyof typeof SCITRADER_THEMES];
const theme = saved ?? SCITRADER_DARK_THEME;

No flash of the wrong theme. With server rendering, keep the choice in a cookie instead, so the server renders the chosen theme on the first paint. The SciTrader app does this.

What a Theme Contains​

GroupWhat it colours
chartBackground, axis strip, gridlines, axis labels and their size, crosshair and its labels, legend text and its size, current-price line, forming-candle wash, zoom rectangle, loading tint, indicator reference lines and bands
candlesThe line and mountain candle types, and point & figure X and O
studiesEach study's default colours, by study type, then by the name of the colour in its settings form: studies.RSI.strokeColor, studies.MACD.bandSignalColor. studies.OHLC holds the candles' colours
marketThe market depth ladder: bid, ask, depth bars, the flash for pulled liquidity, text
uiToolbars, menus, pane controls, buttons, dividers, icons, backgrounds, text, accent, scrollbars, and the gradient of selected icons and primary buttons
drawingThe default colours of drawings. Worked out from ui and chart unless you set them
isDark, fontFamilyWhether the theme is dark, for colours that differ on dark and light backgrounds; the font of the HTML controls

The ISciTraderTheme interface reference on Creating a Custom Theme has every member, with its TSDoc.

Pages in This Section​

PageWhat it covers
The CSS StylesheetImporting it, its CSS variables, overriding its rules, and every class
Creating a Custom ThemeYour own theme, in code or from your CSS
Styling the ChartCandles, indicators, axes, fonts, legend, crosshair, background, drawings
Styling the UI ComponentsToolbars, the market depth ladder, forms and icons
Mobile and Responsive StylingTouch-sized controls, larger text, and following the device's light or dark setting