Angular
@theme-kit/angular
NgModule-free theming: DI providers, reactive injectables, a scoping directive and zero-flash bootstrap helpers.
Installation
Install the package for your framework alongside @theme-kit/core.
pnpm add @theme-kit/angularQuick Start
Start from scratch — install the package, then wrap your app in the provider at the entry point shown below.
1import { bootstrapApplication } from "@angular/platform-browser";
2import { provideThemeKit } from "@theme-kit/angular";
3import { AppComponent } from "./app/app.component";
4import { themes } from "./themes";
5
6bootstrapApplication(AppComponent, {
7 providers: [provideThemeKit({ themes, defaultTheme: "mint-light" })],
8});@theme-kit/core surface, so history, batching, snapshots, packs and lifecycle work the same way across frameworks.Implementation
Read and update theme state from any component using the framework-native primitives below.
1import { provideThemeKit, injectTheme } from "@theme-kit/angular";
2
3bootstrapApplication(AppComponent, {
4 providers: [provideThemeKit({ themes })],
5});
6
7@Component({ ... })
8export class ThemeSwitcher {
9 private theme = injectTheme();
10 // theme().theme() · theme().mode() · theme().setMode("dark")
11}What's Available
@theme-kit/angular ships 16 exports in 5 categories. Everything below is also documented in the full API reference. Click any export to reveal what it does and how to use it.
Setup
Injectables
Transition
Directives
SSR & Bootstrap
Use Cases
The important features in practice — copy any of these straight into your app.
Provide the runtime
Wire Theme Kit once in your app config, then inject reactive state anywhere.
1import { provideThemeKit } from "@theme-kit/angular";
2
3export const appConfig: ApplicationConfig = {
4 providers: [
5 provideThemeKit({ themes, defaultTheme: "light" }),
6 ],
7};Toggle light / dark
injectTheme returns reactive ThemeState with setters.
1import { Component, inject } from "@angular/core";
2import { injectTheme } from "@theme-kit/angular";
3
4@Component({ selector: "app-toggle", template: `
5 <button (click)="theme().toggleTheme()">
6 {{ theme().theme.name }} · {{ theme().mode }}
7 </button>
8` })
9export class ThemeToggleComponent {
10 readonly theme = injectTheme();
11}Undo / redo theme changes
Inject history controls and the runtime for live edits.
1import { Component, inject } from "@angular/core";
2import { injectThemeHistory, injectThemeRuntime } from "@theme-kit/angular";
3
4@Component({ selector: "app-history", template: `
5 <button (click)="history.undo()" [disabled]="!history.history().canUndo">Undo</button>
6 <button (click)="history.redo()" [disabled]="!history.history().canRedo">Redo</button>
7 <button (click)="runtime.update({ colors: { primary: '#6366f1' } })">
8 Make primary indigo
9 </button>
10` })
11export class ThemeHistoryComponent {
12 readonly history = injectThemeHistory();
13 readonly runtime = injectThemeRuntime();
14}Scope a subtree
ThemeScopeDirective themes a single element subtree.
1import { Component } from "@angular/core";
2import { ThemeScopeDirective } from "@theme-kit/angular";
3
4@Component({
5 selector: "app-dashboard",
6 template: `
7 <div class="global-theme">Inherits global</div>
8 <div [themeKitScope]="'forest'">Always forest here</div>
9 `,
10 standalone: true,
11 imports: [ThemeScopeDirective],
12})
13export class DashboardComponent {}Smooth theme transitions
Enable CSS transitions on theme changes for a polished user experience.
1import { provideThemeKit } from "@theme-kit/angular";
2
3export const appConfig: ApplicationConfig = {
4 providers: [
5 provideThemeKit({
6 themes,
7 defaultTheme: "light",
8 transition: { enabled: true, duration: 300, easing: "ease-in-out" },
9 }),
10 ],
11};More Examples
Scoped theming, history controls, and framework-specific patterns.
1import { Component } from "@angular/core";
2import {
3 provideThemeKit,
4 injectThemeHistory,
5 ThemeScopeDirective,
6} from "@theme-kit/angular";
7
8bootstrapApplication(AppComponent, {
9 providers: [provideThemeKit({ themes })],
10});
11
12@Component({
13 selector: "history-controls",
14 standalone: true,
15 imports: [ThemeScopeDirective],
16 template: `
17 <div [themeKitScope]="'forest'" [themeKitScopeTransition]="transition">Scoped to forest</div>
18 <button (click)="undo()" [disabled]="!canUndo()">Undo</button>
19 <button (click)="redo()" [disabled]="!canRedo()">Redo</button>
20 `,
21})
22export class HistoryControls {
23 private history = injectThemeHistory();
24 canUndo() { return this.history.history().canUndo; }
25 canRedo() { return this.history.history().canRedo; }
26 undo() { this.history.undo(); }
27 redo() { this.history.redo(); }
28
29 transition: import("@theme-kit/core").ThemeTransitionOptions = { duration: 300, easing: "ease" };
30}API Reference
Setup
| Export | Description |
|---|---|
provideThemeKit(options) | App-level providers from a ThemeRuntimeOptions config. |
provideThemeKitRuntime(runtime) | Provide an existing shared runtime instance. |
Injectables
| Export | Description |
|---|---|
injectThemeRuntime() | Inject the full runtime. |
injectTheme() | Reactive `ThemeState` — theme, mode, family plus setters. |
injectThemeHistory() | Undo / redo / jump through theme history. |
injectThemeBatch() | Atomic, coalesced updates. |
injectThemeSnapshot() / injectThemeRestore() | Serialize and restore runtime state. |
injectThemeTimeTravel() | `{ history, jump }` — indexed time travel. |
injectThemeLifecycle() | Subscribe to lifecycle events. |
injectThemePacks() | Install theme packs at runtime. |
injectThemeSchedule() | Reactive sunrise/sunset controller: `state()` is a Signal of `enabled`, `status`, `sunrise`, `sunset`, `nextTransition`; plus `enable()`/`disable()`/`set()`. Configure via `scheduled` in `provideThemeKit()`. |
Transition
| Export | Description |
|---|---|
transition in provideThemeKit() | Pass `transition` config to `provideThemeKit()` to enable CSS transitions on theme changes. |
runtime.store.set(theme, { suppressTransition: true }) | Runtime toggle — no mutation hook exists. The transition prop is fixed at runtime creation; for a one-off instant switch, injectThemeRuntime() then runtime.store.set(theme, { suppressTransition: true }) applies immediately without animating. For full control, compose createTransitionPlan + runThemeAnimation from @theme-kit/core. |
Directives
| Export | Description |
|---|---|
ThemeScopeDirective | Element-scoped theming via a directive. |
SSR & Bootstrap
| Export | Description |
|---|---|
createAngularPersistence() | Angular-flavored persistence adapter. |
createBlockingScriptContent / buildThemeCSSMap | Zero-flash bootstrap helpers for server-rendered apps. |