npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@rb-mwindh/ngx-theme-manager

v22.0.0

Published

Angular component to switch between different theming stylesheets

Readme

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


Table of Contents

Compatibility

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.

How it works

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.

Getting Started

Install the package

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

Implement your theme stylesheets

@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';

Load your theme stylesheets

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 { ... }

Implement your theme-picker component

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 and Observables

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);
}

Initial theme selection

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.

Configure synchronization

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.

Migrating to the signal-based API

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.

Building and Testing

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

Contribution Guidelines

Thank you for your interest in contributing to this library.

Please read the Contribution Guidelines

Get help

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.

About

Maintainers

Contributors

  • none ;(

3rd Party Licenses

| 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 | | zone.js | MIT | Dependency |

License

License