Angular Signals Course

Appearance

Pick the palette the course is painted in. Your choice is saved in this browser and applied the next time you open it.

Colour palette

Following your system, which is asking for the light palette right now.

How this screen works

This isn't a detour from the course — the theme switcher is built out of exactly the three primitives from Stage 1. Two signal()s hold the raw facts (what you picked, and what the OS currently wants), a computed() derives the palette actually in force, and a single effect() performs the two side effects: stamping the DOM and writing to local storage.

ts · core/theme.ts
// core/theme.ts — the picker you're using is three primitives deep.
readonly choice = signal<ThemeChoice>(readStoredChoice());
private readonly prefersDark = signal(matchesDark());

readonly resolved = computed<ResolvedTheme>(() => {
  const choice = this.choice();
  if (choice !== 'system') return choice;
  return this.prefersDark() ? 'dark' : 'light';
});

constructor() {
  effect(() => {
    document.documentElement.dataset['theme'] = this.resolved();
    localStorage.setItem(THEME_STORAGE_KEY, this.choice());
  });
}

Note what the effect is not doing: it never reads the palette back out of the DOM to decide what to do next. State flows one way — signals in, side effect out. That's the discipline Module 3 argues for, applied to the app you're reading it in.