Skip to content
EliteChart

Themes and tokens

The CSS-variable token system, partial patches, runtime theme swaps, and the dark/light contract.

EliteChart is driven by two coordinated palettes that always stay in sync:

  1. CSS variables — control the surrounding UI chrome (bars, sidebars, buttons, modals).
  2. Chart theme tokens — control the canvas itself (candle colors, grid, crosshair, price pill).

The shipped @elitechart/elitechart/styles.css wires both palettes together so the UI and the canvas always match. You customise by overriding either side.

Quick example

code
'use client';
import { EliteChart, useThemeStore } from '@elitechart/elitechart';
import { useEffect } from 'react';
import '@elitechart/elitechart/styles.css';

export default function Page() {
  useEffect(() => {
    useThemeStore.getState().setOverride('seriesUp', '#22d3ee');
    useThemeStore.getState().setOverride('seriesDown', '#f43f5e');
  }, []);
  return (
    <div style={{ width: '100%', height: '100vh' }}>
      <EliteChart symbol="BTCUSD" timeframe="1h" />
    </div>
  );
}

How it works

EliteChart ships two palettes — html.dark and html.light — toggled at runtime via the top-bar moon/sun icon and persisted to localStorage['elitechart-ui'].

Three customisation paths, in order of permanence:

  1. CSS variable overrides — drop a stylesheet that overrides --accent-blue, --up, --down, --bg-primary, etc. on html.dark and html.light. Permanent.
  2. useThemeStore.setOverride(key, value) — patch a single token at runtime. Persists to localStorage.
  3. chart.patchTheme(...) via handle.patchTheme — session-only tweaks; reset on reload.

Brand colors — CSS overrides

code
/* your-brand.css — load AFTER @elitechart/elitechart/styles.css */
html.dark {
  --accent-blue: #f43f5e;
  --up: #22d3ee;
  --down: #f43f5e;
  --bg-primary: #09090b;
}
html.light {
  --accent-blue: #e11d48;
  --up: #0e8a74;
  --down: #d32424;
  --bg-primary: #ffffff;
}

Token reference

Backgrounds

VariableRole
--bg-primaryCanvas background + shell base
--bg-secondaryFloating panels, drawers, modals
--bg-tertiaryElevated cards within panels

Series (P&L semantic)

VariableRole
--upBullish candle / positive P&L
--up-softLow-alpha tint for bullish fills
--downBearish candle / negative P&L
--down-softLow-alpha tint for bearish fills

Accent

VariableRole
--accent-bluePrimary accent (buttons, focus, toasts)
--accent-blue-hoverHover state of accent

Text

VariableRole
--text-primaryPrimary body text
--text-secondarySecondary labels
--text-tertiaryMetadata, timestamps, captions

Sizing (vw-clamped)

VariableRole
--topbar-hTop bar height
--leftbar-wLeft rail width
--rightbar-rail-wRight sidebar collapsed width
--rightbar-panel-wRight sidebar expanded width
--bottombar-hBottom strip height
--bottom-drawer-hBottom drawer height when open
--fs-2xs--fs-lgFont size scale

Chart canvas tokens (in-session overrides)

The Settings → Appearance tab and the theme studio example expose four chart-canvas tokens: bullish candle, bearish candle, background canvas, grid. These bind to chart.patchTheme(...) under the hood and reset on reload. For permanent branding use the CSS variable approach above.

Variations

Programmatic theme swap

code
import { useChartHandle } from '@elitechart/elitechart';
import { darkTheme, lightTheme } from '@elitechart/themes';

function MyToggle() {
  const handle = useChartHandle();
  return (
    <button onClick={() => handle?.setTheme(darkTheme)}>Dark</button>
  );
}

Patch just a few tokens

code
handle?.patchTheme({ bgCanvas: '#0f172a', seriesUp: '#22d3ee' });

WCAG contrast

The default tokens pass WCAG 2.1 AA on both palettes (≥ 4.5:1 for body text, ≥ 3:1 for large text). If you override, validate against the canvas using the axe-core devtools extension.