Dark mode is two cooperating pieces: a runtime preference that toggles a single class, and a theme that reacts to it.
dark class@awdlab/jig manages the light/dark preference and, in the browser, toggles a
dark class on the <html> element. The emitted theme CSS keys its dark values off that
class — a theme's dark tokens land under :root.dark { … }. So the class is the switch,
and the theme's dark block (nova reverses its palette — see Colors) is
what the switch activates. This is a class, not a prefers-color-scheme media query:
the media query is only used to detect the system preference, which is then translated
into the class.
Add the withAutoColorScheme() feature to the provider. This is required — it's what
registers the service and eagerly instantiates it so the class actually toggles:
import { provideJigControls, withAutoColorScheme } from '@awdlab/jig/api/ng';
import { nova } from '@awdlab/jig-themes/nova';
provideJigControls(
{ theme: { preset: nova } },
withAutoColorScheme() // persists to localStorage by default
);With no stored preference the initial value is 'system', so the UI follows the OS and
live-updates when the OS scheme changes. Pass withAutoColorScheme({ storage: 'session' })
or a custom storage object to change persistence.
Inject ColorSchemeService:
import { ColorSchemeService } from '@awdlab/jig/api/ng';
export class ThemeToggle {
private readonly scheme = inject(ColorSchemeService);
toggle() {
this.scheme.set('dark'); // 'light' | 'dark' | 'system'
this.scheme.cycle(); // light → dark → system → light
}
readonly pref = this.scheme.preference; // raw choice: 'light' | 'dark' | 'system'
readonly resolved = this.scheme.resolved; // 'system' collapsed to 'light' | 'dark'
readonly isDark = this.scheme.isDark; // boolean
}Avoiding a flash. Because the class is applied after Angular boots, add a tiny inline script to
index.htmlthat reads the stored preference (andprefers-color-scheme) and sets thedarkclass before first paint. ThecolorSchemeInitScript()helper generates one; keep its storage key (jig-color-scheme) in sync.
The dark class does nothing on its own — it only activates rules the theme emits from
its dark block. nova, shade, and material all define one. A theme with no dark
block looks identical in both schemes.
jig