Core

Theming · Light, Dark & Custom

Themes are driven entirely by design tokens. Switch with a single data-theme attribute on <html>, toggle from JS via ng.theme, or define your own brand theme by overriding --ng-* variables. No duplicate CSS.

1 · The data-theme attribute

Light is the default; dark is built in. Set the theme declaratively on the root element — every --ng-* token adapts, no extra stylesheet.

index.html
<!-- on the <html> tag -->
<html data-theme="dark"> … </html>

2 · Switch from JavaScript — ng.theme

The ng_theme.js module exposes a small API on window.ng.theme. set() persists the choice; apply() only previews it.

theme.js
// window.ng.theme (requires ng_theme.js)
ng.theme.set('dark');      // set + persist  (null = auto)
ng.theme.get();            // 'auto' | 'light' | 'dark' | '<name>'
ng.theme.toggle();         // light <-> dark
ng.theme.apply('light');   // preview only, no persist

Wire it to any control — e.g. a toggle button:

index.html
<button onclick="ng.theme.toggle()">Toggle theme</button>

3 · React to changes — ng:theme:change

Every change dispatches ng:theme:change on <html>, with the new value in detail.theme.

theme.js
document.documentElement.addEventListener('ng:theme:change', (e) => {
    console.log(e.detail.theme);   // 'light' | 'dark' | '<name>' | null
});

4 · Persistence (no flash)

The choice is stored in localStorage under ng-theme and restored automatically. To avoid a flash of the wrong theme on load, set the attribute before the stylesheet, in the <head>:

index.html
<!-- in <head>, BEFORE the stylesheet — prevents the flash -->
<script>try{document.documentElement.setAttribute('data-theme',
localStorage.getItem('ng-theme')||'light');}catch(e){}</script>

5 · Custom theme (your brand)

A custom theme is just a named data-theme that overrides the design tokens you care about. Define it in CSS, then activate it by name.

custom.css
/* a named custom theme = override design tokens */
[data-theme="ocean"] {
    --ng-primary-bg: #0e7490;
    --ng-primary-hover: #0c6378;
    --ng-surface: #0b1f24;
    /* …only the --ng-* tokens you need */
}
theme.js
ng.theme.set('ocean');   // activate the custom theme

Override only the tokens you need (brand colors, surfaces). Everything else inherits the framework defaults. Interactive theme switching requires ng_theme.js in your foot.