5.6 KiB
Phase 5 — Dark Mode
Dark Mode für das Portal (Customer + Admin), gesteuert über den FluxUI Appearance-Switcher. Hub-Frontend bleibt Light-Only.
Status: ✅ abgeschlossen · Aufwand: ~½ Tag (meiste Arbeit war Vorbereitung in Phase 0–4) · Risiko: niedrig
Befund
Beim Start in Phase 5 war faktisch ~95 % der Arbeit schon in den vorherigen Phasen erledigt worden. Konkret:
Was bereits da war
-
shared/design-tokens.csshat einen kompletten.dark { … }-Block (Z. 182–248) mit:- Surfaces (bg, bg-elev, bg-rule, bg-card, bg-card-warm)
- Hub-Blau (heller im Dark Mode:
#5a78c2) - Bernstein (heller:
#d9a560),--color-accent-warmbewusst konstant - Ink-Skala (invertiert)
- Status-Farben (ok/warn/err in helleren Varianten)
- Bridge-Dots (heller)
- Schatten (neutral schwarz statt warm-blau)
color-scheme: darkfür native Controls
-
portal.csshat:@custom-variant dark (&:where(.dark, .dark *))für Tailwind-dark:-Variants- Dark-Mode Shadow-Overrides für FluxUI-Primary-Buttons
- Klare Erläuterung, warum kein Notfall-
.dark { … }-Hack mehr nötig ist
-
shared/hub-components.cssist zu 100 % token-basiert (panels, badges, view-tabs, filter-chips, active-chips, portal-pills, inline-actions, empty-stage, counter-strip). Sobald die Tokens umschalten, schalten alle Komponenten automatisch um. -
panel-darknutzt--color-panel-dark-2/--color-panel-dark— die sind in beiden Modi identisch. Die Brand-Bridge-Card bleibt damit immer dunkel. -
@fluxAppearanceist in beiden Head-Partials eingebunden (partials/head.blade.php+partials/admin-head.blade.php). -
Switcher ist an drei Stellen verfügbar:
- Sidebar Desktop User-Menü
(
components/layouts/app/sidebar.blade.php) - Sidebar Mobile User-Menü (gleiche Datei)
settings/appearance.blade.php(volle Card mit Light/Dark/System) Alle drei nutzenx-model="$flux.appearance"— FluxUI's Magic-Object, das LocalStorage-persistent ist und automatischclass="dark"auf<html>setzt.
- Sidebar Desktop User-Menü
(
Was zu fixen war
Bei der Inventur fielen nur zwei Stellen auf, die im Dark Mode brechen würden:
-
customer/tokens.blade.phpZ. 137: Token-Anzeige nach Generierung nutzte ein nicht existentes--color-ink-deep-Token. Damit war der Hintergrund bisher schlicht transparent (Light: kaum sichtbar, Dark: ebenso). Außerdem würde--color-inkim Dark Mode hell werden — weißer Text auf hellem Bg wäre unlesbar. Fix: auf--color-panel-dark-2(konstant dunkel) umstellen. -
customer/security.blade.phpZ. 270: 2FA-QR-Code inbg-white-Block. Das ist bewusst so — QR-Codes brauchen schwarz-auf-weiß, sonst werden sie nicht eingescannt. Kein Fix, nur Kommentar zur Klarstellung.
Was unkritisch ist
customer/dashboard.blade.php: 8 Treffer fürbg-white/text-white— alle impanel-darkBrand-Bridge Block (konstant dunkel, weiße Texte korrekt) und im Empty-State Counter-Badge auf--color-accent(Bernstein-Bg, beides Modi).admin/dashboard.blade.phpZ. 235: Quick-Action Hover-Stategroup-hover:bg-hub group-hover:text-white— Hub-Bg ist sowohl Light (dunkles Hub-Blau) als auch Dark (helleres Hub-Blau) okay für weißen Text.- Sidebar-
dark:bg-zinc-…Klassen aus dem Starter-Kit: Die Zinc-Skala ist inportal.cssauf warmes Buchpapier gemapped, das funktioniert weiter — die Avatar-Bg's sind sowieso nur 8×8-Pixel-Spots. customer/press-kits/show.blade.phpZ. 440: Logo-Bgbg-white— bewusst, weil Firmen-Logos einen weißen Hintergrund für korrekte Darstellung brauchen.
Was außerhalb von Phase 5 ist
shared-styles.csshat.dark .card,.dark .slider-*,.dark .highlight-*,.dark .section-*Regeln. Diese sind für den Web-Bereich (Hub-Frontend, presseecho, businessportal24), nicht fürs Portal.portal.cssimportiertshared-styles.cssnicht — die Regeln landen also nicht im Portal-Bundle.- Web-Frontend bleibt Light-Only — wie in der Roadmap definiert.
Akzeptanzkriterien
- Plan
- Recherche aller hardcoded Farbklassen
--color-ink-deep→--color-panel-dark-2incustomer/tokens.blade.phpbg-whitefür 2FA-QR-Code insecurity.blade.phpmit erklärendem Kommentar versehen- Build + Pint + Tests grün
- PROGRESS.md + 03-WEITERE-PHASEN.md auf ✅
Lessons Learned
- Konsequente Token-Disziplin (kein Hex außer in
design-tokens.css) zahlt sich beim Dark Mode massiv aus: Statt 15 Pages × dutzende Klassen anzufassen, schaltet das gesamte Portal mit einem.dark {…}Block um. - Die wenigen Ausnahmen (panel-dark, QR-Code-Bg, Logo-Bg) sind dokumentierte Bewusst-Entscheidungen, keine Schuld.
- FluxUI's
$flux.appearanceMagic-Object spart eine eigene Alpine-Component und persistiert über LocalStorage.
Manueller Smoke-Test (Empfehlung)
Da Pest keine echte Browser-Rendering-Pipeline hat:
- Im Browser: User-Menü → Erscheinung → „Dunkel"
- Folgende Seiten besuchen + visuell prüfen:
/dashboard(Admin) +/me/dashboard(Customer)/me/press-releases(Customer-Liste mit Saved-Views-Tabs, Filter-Chips, Portal-Pills, Row-Tints)/admin/press-releases(Admin-Liste mit Inline-Actions)/me/security(2FA-QR mitbg-white)/me/tokens(Token-Anzeige nach Generierung)/admin/companies/{id}(Detail-View mit allen Panels)
- Erwartung: Lesbar, konsistent, keine grellen Kontraste, keine „weißen Inseln" auf dunklem Bg.