Theme-Umschalter

sitelo-ui löst den Dunkelmodus von sich aus über prefers-color-scheme auf — eine Website, die zufrieden dem Betriebssystem folgt, braucht von dieser Seite nichts. Der Umschalter ist dafür da, eine Leserin das überstimmen zu lassen.

Er ist eine der fünf Komponenten, die ein Skript brauchen, denn die Wahl liegt im localStorage und nur ein Skript kann sie lesen. Der Button holt sich dieses Skript beim ersten Druck selbst.

Einrichtung

Zwei Dinge in den Head, und der Button dorthin, wo er hingehört:

import { styles, themeScript, themeToggle } from 'sitelo/ui'

head(
  themeScript(), // wendet die gespeicherte Wahl vor dem ersten Paint an
  styles(),
)

body(
  appBar({ brand: 'Meine Website' },
    appBarSpacer(),
    appBarActions(themeToggle()),
  ),
)

Eine dritte Datei gibt es nicht. themeScript() ist mit Absicht blockierend und inline — alles Verzögerte malt zuerst, und genau das ist das dunkle Aufblitzen, das es verhindern soll — und das Umschalten selbst reitet auf dem Button mit:

<button data-su-theme-toggle
        onclick="import('/su/theme.js').then(m=>m.toggle(this))">

Setze beide zusammen ein. themeScript() ist auch das, was den Umschalter beim Laden mit aria-pressed markiert: gedrückt wurde noch nichts, also kann der Button allein gar nicht wissen, welches Theme herauskam.

Der Umschalter

Das Icon ist reines CSS, direkt vom Theme-Attribut abgelesen — es stimmt also schon beim ersten Paint, bevor ein Skript läuft. Es zeigt, wohin ein Klick umschaltet.

stack({ direction: 'row', gap: 'md', align: 'center' },
  themeToggle(),
  themeToggle({ variant: 'soft' }),
  themeToggle({ variant: 'outline' }),
)

Diese Buttons funktionieren — diese Seite lädt das Runtime. Ein Klick setzt data-su-theme am <html>, das eigene Attribut von sitelo-ui, deshalb ändern sich nur die sitelo-ui-Komponenten auf dieser Seite. Der Rest dieser Website folgt ihrem eigenen data-theme, gesetzt vom Umschalter in der oberen Leiste. Auf deiner Website gäbe es davon nur einen.

In einer App-Bar

sitelo
appBar({ brand: 'sitelo' },
  appBarNav(navLink({ href: '#docs', current: true }, 'Doku')),
  appBarSpacer(),
  appBarActions(
    themeToggle(),
    button({ size: 'sm' }, 'Loslegen'),
  ),
)

Wie das Theme aufgelöst wird

Der Reihe nach: ein explizites data-theme oder data-su-theme an irgendeinem Vorfahren gewinnt; sonst entscheidet prefers-color-scheme. Beide Attributnamen werden beachtet, damit sitelo-ui in einer Website sitzen kann, die schon ihren eigenen Theme-Schalter hat — genau das tut diese Dokumentation.

Selbst steuern

Das Runtime exportiert dieselben Funktionen, die der Button nutzt — für ein eigenes Bedienelement oder eine Dreifachauswahl hell / dunkel / System.

import { getTheme, setTheme, toggleTheme } from 'sitelo/ui/client'

getTheme()          // 'light' | 'dark' — aufgelöst, nicht gespeichert
toggleTheme()       // umschalten
setTheme('dark')    // festlegen
setTheme('system')  // die Übersteuerung löschen und wieder dem OS folgen

Props

PropTypStandardBeschreibung
labelstring'Toggle dark mode'Zugänglicher Name und Tooltip.
variant'solid' | 'soft' | 'outline' | 'ghost' | 'link''ghost'Button-Variante.
color'primary' | 'neutral' | 'success' | 'warning' | 'danger''neutral'Aus welcher Palette geschöpft wird.

themeScript() nimmt ein optionales nonce — für eine Website mit Content Security Policy.