Dienstag, 27. Januar 2020

So implementierst Du den Dark / Light Mode in Angular Material mit prefers-color-scheme

Das erste Mal aufgefallen sind mir Dark Themes in meiner Jugend als ich angefangen habe StarCraft zu spielen und die offiziellen Blizzard-Webseiten und Foren besucht habe. Ich empfand Blizzard UI Designs immer als sehr ansprechend und intuitiv. Außerdem prägten sie sich schnell ein und blieben, wie man an dieser Artikeleinleitung sieht, lange in Erinnerung.

Gerade als junger "Zocker" verbringt man einen sehr großen Teil seiner Spielzeit nachts vor dem PC und fühlt sich schnell von hellen Lichtquellen gestört. Ich erinnere mich noch, wie ich scherzhaft einem Freund erklärte, dass es eine gute Idee sei, sich eine Sonnenbrille für nachts zu kaufen. Somit könne man auch endlich nachts im stockfinsteren Zimmer surfen, ohne blind werden zu müssen.

Blog Figure
Illustration von GreedyMoonBear

Mit den Jahren kamen immer mehr Artikel, Statistiken und Gründe die für einen Dark Mode sprechen. Diese könnt ihr diesem schönen Artikel von Thomas Steiner entnehmen. Ich persönlich nutze fast in jedem meiner Angular-Projekte Material, welches bereits von Haus aus die Möglichkeit bietet sein Default Theming auf Dark oder Light zu stellen. Hier ein ganz einfaches Beispiel für eine App, die sowohl Dark als auch Light Mode in einer Angular Material App unterstützt:

style.scss mit basic Material Theming.

Nun hängt man einfach einem übergeordneten Element die class color-scheme-dark oder color-scheme-light an und die Elemente färben sich im gewünschten Theme Mode.

Manche Material Components, wie beispielsweise der mat-dialog, binden sich beim Ausführen auf oberster Ebene im HTML DOM ein (also noch außerhalb der app.component). Daher ist es empfehlenswert die prefers-color-scheme classes im body Tag zu setzen!

Um dem ganzen Leben einzuhauchen, würde meine Empfehlung für einen Angular Service folgendermaßen aussehen:

color-scheme.service.ts

Ich denke der Code und die Kommentare sind recht selbsterklärend. Es gibt sicherlich komplexere und umfangreichere Lösungen. Ich persönlich mag jedoch simple Lösungen, die sich ohne große Abänderungen in jedem beliebigen Projekt wiederverwenden lassen.

Was hier geschieht, ist recht simpel: Es wird geschaut, ob der Benutzer in seinem LocalStorage einen Overwrite für seinen OS Default gespeichert hat und wenn nicht, wird geschaut, ob der Browser prefers-color-scheme unterstützt. Wenn ja, dann wird dieser geladen, ansonsten wird per Default in diesem Fall einfach auf Dark gestellt. Außerdem bieten wir eine Möglichkeit die color-scheme umzustellen und uns diese Information aus dem Service ausgeben zu lassen.

Jetzt braucht ihr lediglich die load() Methode in eurer app.component.ts auszuführen, um den Service initial anzustoßen:

app.component.ts

Und das war es auch schon! Jetzt könntet ihr beispielsweise in eurer SideNav eine Option einblenden, bei der man den Theme Mode ändern kann. Eine Beispiel-App habe ich euch hier bereitgestellt:

preferred-color-scheme Demo on StackBlitz

Ich hoffe, einige von euch können damit etwas anfangen und vor allem, dass es nicht mehr allzu lange dauert, bis absolut jede Web-Anwendung einen Dark Mode an Bord hat! 😉

Stay awesome!