import { WrTheme, wrThemePrePaintScript } from 'ngwr/theme';WrTheme
Switch between light, dark and auto, and keep the choice.
Installation
Import the class, and @use the entry point in your global styles: without it the component renders unstyled.
Usage
Needs no provider: inject it where the toggle lives.
private readonly theme = inject(WrTheme);
this.theme.set('dark');
this.theme.toggle();
protected readonly resolved = this.theme.resolved; // Signal<'light' | 'dark'>
protected readonly mode = this.theme.mode; // Signal<'light' | 'dark' | 'auto'>Configuration
withTheme() in provideWr() sets defaultMode and storageKey.
import { provideWr } from 'ngwr';
import { withTheme } from 'ngwr/theme';
bootstrapApplication(AppComponent, {
providers: [
// Defaults: 'auto' and 'wr-theme'; storageKey: null stops persisting.
provideWr(withTheme({ defaultMode: 'dark', storageKey: 'app-theme' })),
],
});SSR: no flash of the wrong theme
Put this script in <head>, above the stylesheets, so a stored choice applies before the first paint.
<script>(function(){try{var m=null,r=null;try{r=window.localStorage.getItem("wr-theme");}catch(e){}if(r!==null){try{var p=JSON.parse(r);if(p!==null&&typeof p==="object"&&"v" in p){if(p.e===undefined||p.e>=Date.now())m=p.v;}else{m=p;}}catch(e){m=r;}}if(m!=="light"&&m!=="dark"&&m!=="auto")m="auto";if(m==="light"||m==="dark")document.documentElement.style.colorScheme=m;}catch(e){}})();</script>import { wrThemePrePaintScript } from 'ngwr/theme';
// Pass the values you gave withTheme() and withStorage():
wrThemePrePaintScript({ storageKey: 'app-theme', defaultMode: 'dark', storagePrefix: 'myapp:' });
// It returns the source without <script>, so a strict CSP can hash it:
const hash = createHash('sha256').update(wrThemePrePaintScript()).digest('base64');Gotchas
- Without
withTheme(), a stored choice applies only once something injectsWrTheme. withTheme()in a route's providers is ignored.- With two Angular apps on one page, only one should inject
WrTheme.
API
| Name | Description | Type | Default |
|---|---|---|---|
mode | The chosen mode: light, dark or auto. | Signal<WrThemeMode> | — |
resolved | The scheme in effect; auto follows the OS. | Signal<'light' | 'dark'> | — |
set(mode) | Switch to a specific mode. | (m: WrThemeMode) => void | — |
toggle() | Flip between light and dark (skips auto). | () => void | — |
WR_THEME_CONFIG | Holds defaultMode and storageKey. Set it with withTheme(). | InjectionToken<WrThemeConfig> | — |
withTheme(config?) | The provideWr() feature: sets WR_THEME_CONFIG and creates WrTheme at boot. | (config?: Partial<WrThemeConfig>) => WrFeature<'theme'> | — |
wrThemePrePaintScript(options?) | Source of the script that applies a stored choice before the first paint. Takes the withTheme() and withStorage() values. | (options?: WrThemePrePaintOptions) => string | — |
Dependencies
| Built on | WrStorage |
|---|
See also
Guide ThemingLoad the theme, switch light and dark, and rebrand the palette.Type Theme typesThe intent and mode unions from ngwr/theme.Docs ConfigurationSet app-wide options at bootstrap.Guide ColorsThe --wr-color-* tokens, and which one to use for fills, text and borders.Guide Server-side renderingPrerender and hydrate an ngwr app without mismatches.Service WrPlatformSSR-safe browser checks, user-preference signals and haptics.Service WrStorageTyped, reactive key-value storage over localStorage or any engine, safe under SSR.