Theming

Light/dark mode, sidebar persistence and styling are all handled with signal-based services and Bootstrap 5.3 conventions. Theming is SSR-safe: all DOM access is guarded behind a platform check.

Dark / light mode

Color mode is managed by ColorModeService (providedIn: 'root'). It tracks the chosen mode ('light' | 'dark' | 'auto'), resolves auto against the system preference, reflects the resolved value onto <html data-bs-theme>, and persists the choice to localStorage['lte-theme'].

  • colorMode — a signal of the user's chosen mode.
  • resolvedMode — a computed signal of the concrete 'light' | 'dark' after auto is evaluated.
  • setColorMode(mode) — set the mode explicitly.
  • cycle() — rotate light → dark → auto.
  • setInitialMode(mode) — apply a default only when nothing is persisted (a saved choice always wins).

The topbar's <lte-color-mode-toggle> drives this for you. To control it from your own UI, inject the service:

import { Component, inject } from '@angular/core';
import { ColorModeService } from '@adminlte/angular';

@Component({ /* ... */ })
export class ThemeButton {
  private readonly colorMode = inject(ColorModeService);
  readonly resolved = this.colorMode.resolvedMode; // signal

  toggle(): void {
    this.colorMode.setColorMode(this.resolved() === 'dark' ? 'light' : 'dark');
  }
}

No flash of the wrong theme

Because Angular boots after the page loads, add the no-flash inline script to index.html so the persisted theme is applied before first paint. The same string is exported as COLOR_MODE_NO_FLASH_SCRIPT for SSR injection. See Installation for the snippet.

Sidebar persistence

SidebarService ports AdminLTE's responsive push-menu logic: on desktop the toggle collapses the sidebar (body.sidebar-collapse); below the breakpoint it opens an overlay (body.sidebar-open). State is reflected onto <body> imperatively (hydration-safe).

Set [enableSidebarPersistence]="true" on the layout to remember the collapse state across reloads. It is stored under localStorage['lte.sidebar.state'] as JSON, e.g. {"collapsed":true}. The service exposes signals (isCollapsed, isMobileOpen, isMiniMode, isMobile) and methods (toggle(), collapse(), expand()) you can drive yourself.

The sidebar's own color (sidebarTheme: 'light' | 'dark') is independent of the global color mode, so you can keep a dark sidebar in light mode.

Customizing styles

AdminLTE 4 and Bootstrap 5.3 are themed with CSS custom properties. The quickest way to recolor the app is to override Bootstrap's variables — scoped per theme via [data-bs-theme] if you want different values in dark mode:

/* src/styles.scss */
:root {
  --bs-primary: #6610f2;
  --bs-primary-rgb: 102, 16, 242;
}

[data-bs-theme="dark"] {
  --bs-body-bg: #14181f;
}

For deeper customization, compile Bootstrap and AdminLTE from their SCSS sources, overriding their Sass variables before the imports, and load your compiled stylesheet instead of @adminlte/angular/css/adminlte.css. Component-scoped tweaks can also go in a standalone component's styles — but note that AdminLTE's structural classes live in the global stylesheet, so most theming belongs at the global level (or behind ::ng-deep when scoping is required).

Fullscreen

FullscreenService wraps the Fullscreen API and keeps its isFullscreen signal in sync with the fullscreenchange event — so exiting with Esc updates the UI. The topbar's <lte-fullscreen-toggle> uses it; call toggle(), enter() or exit() to drive it yourself.


AdminLTE 4 · Angular port Edit on GitHub