@rb-mwindh/ngx-theme-manager - v22.0.1
    Preparing search index...

    @rb-mwindh/ngx-theme-manager - v22.0.1

    ngx-theme-manager

    @rb-mwindh/ngx-theme-manager provides the basics tools for a robust theme-switcher implementation.

    This package does not provide ready-made visual components, but only supports their implementation by providing the necessary services and tools.


    sponsors License latest release

    open issues open pr

    nodejs angular


    As of v18, the package major version follows the supported Angular major version.

    Package version Angular version Development runtime
    22.x Angular 22.x Node.js ^22.22.3, ^24.15.0 or ^26.0.0
    21.x Angular 21.x Node.js ^20.19.0, ^22.12.0 or ^24.0.0
    20.x Angular 20.x Node.js ^20.19.0, ^22.12.0 or ^24.0.0
    19.x Angular 19.x Node.js ^18.19.1, ^20.11.1 or ^22.0.0
    18.x Angular 18.x Node.js ^18.19.1, ^20.11.1 or ^22.0.0

    The published package declares @angular/common and @angular/core version 22 or newer as peer dependencies. The Node.js versions above apply to this repository's development, build and release tooling.

    This implementation is based on the regular way Angular loads component styles. Since theme styles are usually global styles, theme components normally use ViewEncapsulation.None.

    Angular does not provide a direct way to access the <style> element associated with a component. Therefore, @rb-mwindh/ngx-theme-manager identifies theme styles through predefined annotations in CSS comments.

    The library scans the application's <style> elements, registers annotated themes and adds a data-theme="<id>" attribute to the corresponding elements. It then uses the media attribute to activate or deactivate each theme:

    • inactive theme styles receive media="none"
    • active theme styles have their media attribute removed

    Newly added styles are discovered automatically. This also supports themes loaded after application startup.

    npm install @rb-mwindh/ngx-theme-manager --save
    

    @rb-mwindh/ngx-theme-manager identifies CSS, SCSS and other compiled stylesheets as themes through annotations in CSS comments. Use the /*! ... */ comment format so the annotations remain available after production minification.

    ... By default, multi-line comments be stripped from the compiled CSS in compressed mode. If a comment begins with /*!, though, it will always be included in the CSS output. ...

    See the Sass documentation on comments

    Known annotations are:

    Annotation Required Description
    @@id yes Unique theme identifier; reads until the end of the line
    @@displayName no User-facing name; defaults to the theme ID
    @@description no Optional user-facing description
    @@default no Marks the theme as the default theme; does not take a value
    /*!
    * @@id my-theme-id
    * @@displayName My Fantastic Theme
    * @@description This is my fantastic theme with magic colors
    * @@default
    */

    // add all your theme styles below this line, e.g.
    @import '@angular/material/prebuilt-themes/indigo-pink.css';
    @import 'some-other-library/theme.css';

    Use an Angular component to make the compiler pick up and compile the theme stylesheets. The component must use ViewEncapsulation.None so the styles are global.

    @Component({
    selector: 'app-themes',
    template: '', // no template needed
    styleUrls: [
    'assets/themes/theme-a.scss',
    'assets/themes/theme-b.scss',
    'assets/themes/theme-c.scss',
    ], // load all theme stylesheets here
    encapsulation: ViewEncapsulation.None, // make the styles global
    })
    export class AppThemesComponent {
    /* no implementation needed */
    }

    Import and render this component near the root of the application so theme styles are available throughout the application.

    @Component({
    selector: 'app-root',
    template: `
    <app-themes></app-themes>

    <!-- your app template here -->
    `,
    imports: [AppThemesComponent],
    })
    export class AppComponent { ... }

    The package intentionally does not prescribe the appearance of a theme picker. It exposes the registered themes, the current theme and a method for changing the selection.

    Assuming an application provides an app-theme-picker component, it can be connected to ThemeService as follows:

    @Component({
    selector: 'app-root',
    imports: [AppThemePickerComponent],
    template: `
    <app-theme-picker
    [themes]="themeService.themes()"
    [currentTheme]="themeService.currentTheme()"
    (selectionChanged)="themeService.selectTheme($event)"
    />
    `,
    })
    export class AppComponent {
    readonly themeService = inject(ThemeService);
    }

    selectTheme() accepts a registered theme ID. Passing null clears the current in-memory selection. Unknown theme IDs are ignored once themes have been registered.

    Signals are the preferred API for current Angular applications.

    State Signal API Observable compatibility API
    Registered themes themeService.themes() themeService.themes$
    Current theme ID themeService.currentTheme() themeService.currentTheme$

    The Observable APIs remain available for applications that use RxJS-based state handling or the async pipe.

    @Component({
    selector: 'app-current-theme',
    imports: [AsyncPipe],
    template: `Current theme: {{ themeService.currentTheme$ | async }}`,
    })
    export class CurrentThemeComponent {
    readonly themeService = inject(ThemeService);
    }

    After the first themes have been discovered, the initial selection is resolved in this order:

    Priority Source
    1 Valid theme ID from the configured URL query parameter
    2 Valid theme ID from the configured browser storage entry
    3 Theme annotated with @@default
    4 First registered theme

    Unknown route or storage values are ignored. If no themes are registered, the current theme remains null.

    By default, the selected theme is synchronized with:

    Integration Default value
    Browser storage key ngx-theme-manager/current-theme
    URL query parameter theme

    Both integrations are optional. Angular Router itself is also optional; applications without Router can use the package without additional configuration.

    Use provideThemeManager() to customize the storage key and query parameter:

    import { ApplicationConfig } from '@angular/core';
    import { provideThemeManager } from '@rb-mwindh/ngx-theme-manager';

    export const appConfig: ApplicationConfig = {
    providers: [
    provideThemeManager({
    storageKey: 'my-application/current-theme',
    queryParam: 'app-theme',
    }),
    ],
    };

    To disable either integration, provide null or an empty string:

    import { ApplicationConfig } from '@angular/core';
    import { provideThemeManager } from '@rb-mwindh/ngx-theme-manager';

    export const appConfig: ApplicationConfig = {
    providers: [
    provideThemeManager({
    storageKey: '',
    queryParam: null,
    }),
    ],
    };

    Only specify the options you want to customize. All omitted options retain their default values.

    The signal-based state API can replace template subscriptions without requiring a breaking migration. The Observable APIs remain supported.

    Previous Observable usage Preferred signal usage
    themeService.themes$ | async themeService.themes()
    themeService.currentTheme$ | async themeService.currentTheme()

    The Theme interface now exposes immutable metadata. Construct theme metadata as readonly data and replace objects instead of mutating individual properties.

    import { Theme } from '@rb-mwindh/ngx-theme-manager';

    const darkTheme: Theme = {
    id: 'dark',
    displayName: 'Dark',
    description: 'Dark application theme',
    defaultTheme: true,
    };

    The demo application uses standalone APIs and signals, but the library does not require a specific application bootstrap style.

    This repository requires one of the supported Node.js versions listed in the compatibility table.

    1. Clone the repository
    git clone https://github.com/rb-mwindh/ngx-theme-manager.git <workspace>
    cd <workspace>
    1. Install the dependencies
    npm ci
    

    npm ci installs the exact dependency versions recorded in package-lock.json. This is the recommended way to install dependencies for development and testing.

    During installation, npm automatically runs the prepare script, which configures the repository's Husky Git hooks. No separate initialization command is required.

    1. Run the demo app
    npm run start
    
    1. Build the library
    npm run build
    
    1. Run the local validation pipeline:
    npm run typecheck
    npm run lint
    npm run test

    Thank you for your interest in contributing to this library.

    Please read the Contribution Guidelines

    Please check my wiki::faq and wiki::troubleshooting wiki page first.

    If this doesn't answer your question, you may post a question to the issue tracker.

    • none ;(
    Name License Type
    @angular/animations MIT Dependency
    @angular/cdk MIT Dependency
    @angular/common MIT Dependency
    @angular/compiler MIT Dependency
    @angular/core MIT Dependency
    @angular/forms MIT Dependency
    @angular/platform-browser MIT Dependency
    @angular/platform-browser-dynamic MIT Dependency
    @angular/router MIT Dependency
    @standard-schema/spec MIT Dependency
    entities BSD-2-Clause Dependency
    material-icons Apache-2.0 Dependency
    ngx-theme-manager MIT Dependency
    parse5 MIT Dependency
    rxjs Apache-2.0 Dependency
    tslib 0BSD Dependency
    zod MIT Dependency
    zone.js MIT Dependency

    License