Files
AfiS-Aktensystem/web/components/ThemeToggle.tsx
T
Harlekin e0b03ea336
Prüfung / Lint, Typen, Tests (push) Canceled after 0s
Prüfung / Images bauen (pdf) (push) Canceled after 0s
Prüfung / Images bauen (web) (push) Canceled after 0s
Prüfung / Images bauen (worker) (push) Canceled after 0s
Images / bauen (pdf, docker/pdf.Dockerfile) (push) Canceled after 0s
Images / bauen (web, docker/web.Dockerfile) (push) Canceled after 0s
Images / bauen (worker, docker/worker.Dockerfile) (push) Canceled after 0s
Gedankenstriche durch Bindestriche ersetzt
375 Vorkommen in 210 Dateien. Betrifft Kommentare, Oberflaechentexte und die
README; an keiner Stelle Bedeutung, nur Zeichensetzung.
2026-09-04 08:54:52 +02:00

60 lines
1.7 KiB
TypeScript

'use client'
import { useEffect, useState } from 'react'
import { themeText } from '@/lib/i18n/shell'
type Thema = 'dark' | 'light' | 'system'
export const THEME_KEY = 'afis:thema'
/**
* Umschalter zwischen dunklem und hellem Thema.
*
* Drei Zustände, nicht zwei: „System" ist der Auslieferungszustand und folgt
* `prefers-color-scheme`. Wer ausdrücklich wählt, bekommt seine Wahl auf
* diesem Gerät gemerkt - nicht am Konto, denn es ist eine Eigenschaft des
* Bildschirms, an dem jemand sitzt, nicht der Person.
*
* Gesetzt wird das Attribut schon vor dem ersten Malen, siehe das Skript im
* Wurzel-Layout. Sonst blitzt beim Laden das falsche Thema auf.
*/
export function ThemeToggle() {
const [thema, setThema] = useState<Thema>('system')
useEffect(() => {
try {
const gespeichert = localStorage.getItem(THEME_KEY)
if (gespeichert === 'dark' || gespeichert === 'light') setThema(gespeichert)
} catch {
// Privates Fenster: dann eben ohne Merken.
}
}, [])
function waehlen(neu: Thema) {
setThema(neu)
try {
if (neu === 'system') localStorage.removeItem(THEME_KEY)
else localStorage.setItem(THEME_KEY, neu)
} catch {
// s. o.
}
const wurzel = document.documentElement
if (neu === 'system') wurzel.removeAttribute('data-theme')
else wurzel.setAttribute('data-theme', neu)
}
return (
<select
value={thema}
onChange={(event) => waehlen(event.target.value as Thema)}
aria-label={themeText.label}
className="field text-2xs"
>
<option value="system">{themeText.system}</option>
<option value="dark">{themeText.dark}</option>
<option value="light">{themeText.light}</option>
</select>
)
}