Umbenennung presseportale → pressekonto in Domains, Themes und Dokumentation. Design-Tokens, Portal-Shell, Customer-Dashboard, Auth- und Admin-PM-Views. Artisan-Befehl migrate:legacy-media mit Tests und Hub-Flux-Entwicklungsdocs. Co-authored-by: Cursor <cursoragent@cursor.com>
159 lines
7.8 KiB
Markdown
159 lines
7.8 KiB
Markdown
# Phase 5 — Dark Mode konsistent + Appearance-Switcher im User-Menü
|
|
|
|
> **Vorzugsphase**: Eigentlich Phase 5, vorgezogen vor Phase 3/4 nach
|
|
> User-Wunsch. Grund: Der FluxUI-Appearance-Switcher hat in Phase 1 den
|
|
> Dark-Mode-Bug ausgelöst (`#6d8ad3` statt Hub-Blau); statt Symptom-Fix
|
|
> wollen wir den vollen Dark Mode jetzt richtig.
|
|
|
|
**Status**: ✅ abgeschlossen · **Aufwand**: ~½ Tag · **Risiko**: niedrig
|
|
|
|
---
|
|
|
|
## Ziele
|
|
|
|
1. Dark Mode funktioniert sauber auf allen Portal-Seiten (Customer-Dashboard,
|
|
Sidebar, FluxUI-Komponenten, Hub-Components).
|
|
2. Switcher (Light / Dark / System) **direkt im User-Menü** verfügbar — kein
|
|
Umweg über `/settings/appearance` mehr nötig.
|
|
3. Hub-Frontend (Landing + Auth) bleibt **bewusst Light-Only** — Hub-Atmosphäre
|
|
ist Buchpapier.
|
|
4. Der Notfall-Hack aus Phase 1 (`portal.css: .dark { --color-accent: var(--color-hub) }`)
|
|
wird durch das echte Dark-Token-Mapping ersetzt.
|
|
|
|
## Quelle der Wahrheit
|
|
|
|
`dev/frontend/tailwind_v3/User Dashboard presseportale Dark.html` —
|
|
liefert alle Dark-Werte. Wir spiegeln die Token-Namen aus dem Light-Mode 1:1.
|
|
|
|
---
|
|
|
|
## Was sich ändert
|
|
|
|
### 1. `shared/design-tokens.css`
|
|
|
|
Der seit Phase 0 vorbereitete `.dark`-Block wird **aktiviert** und um die seit
|
|
Phase 2 nachgezogenen Tokens (`--color-bg-rule-2`, `--color-gain-deep`) ergänzt.
|
|
|
|
Wichtige Umwidmungen im Dark Mode (gleiche Namen, andere Werte):
|
|
|
|
| Token | Light | Dark | Bedeutung |
|
|
| ----------------------- | ----------- | ----------- | ------------------------------------------ |
|
|
| `--color-bg` | `#f6f4ef` | `#0e1218` | Page-Background |
|
|
| `--color-bg-elev` | `#fbfaf6` | `#14181f` | Sidebar / leicht hervorgehoben |
|
|
| `--color-bg-card` | `#ffffff` | `#181d27` | Card-Body |
|
|
| `--color-bg-rule` | `#e2ddd0` | `#2a3142` | Trennlinien |
|
|
| `--color-bg-rule-2` | `#ede7d7` | `#232838` | Progress-Track |
|
|
| `--color-hub` | `#1a2540` | `#5a78c2` | Primary-Akzent (heller im Dark) |
|
|
| `--color-hub-soft` | `#e5e9f1` | `#1f2a47` | Hint-Hintergrund |
|
|
| `--color-accent` | `#b07a3a` | `#d9a560` | Bernstein-Akzent (heller im Dark) |
|
|
| `--color-accent-warm` | `#b07a3a` | `#b07a3a` | **bleibt gleich** — für Border-Akzente |
|
|
| `--color-accent-deep` | `#8a5e27` | `#b07a3a` | Action-Link-Color (heller im Dark) |
|
|
| `--color-accent-soft` | `#f1e6d3` | `#2a2418` | Hint-Icon-BG |
|
|
| `--color-ink` | `#1a1f1c` | `#ece9e0` | Text-Primary |
|
|
| `--color-ink-2` | `#3a413d` | `#c9c5b8` | Text-Secondary |
|
|
| `--color-ok / -soft` | `#2e8540 / #e2f1e5` | `#4dc076 / #1a2d22` | Status grün |
|
|
|
|
`--color-accent-warm` als **konstanter** Bernstein-Token (gleicher Wert in
|
|
beiden Modi) ist ein bewusster Trick: Im Portal mapt `--color-accent` auf
|
|
`var(--color-hub)` (Primary-Akzent), aber Bernstein-Borders (Hint-Card,
|
|
Schritt-Karten-Eyebrow) brauchen weiterhin den ungeänderten Bernstein-Wert.
|
|
`--color-accent-warm` ist der Token dafür.
|
|
|
|
### 2. `portal.css`
|
|
|
|
- Den `.dark { --color-accent: var(--color-hub); … }`-Notfall-Block aus
|
|
Phase 1 entfernen — er ist mit echtem Dark-Mapping überflüssig.
|
|
- Stattdessen einen kurzen Kommentar setzen, dass das Token-Mapping aus
|
|
`design-tokens.css` greift.
|
|
- Primary-Button-Hover-Override: heute hartcodiert auf `--color-hub-2`
|
|
(`#243152`). Im Dark Mode ist `--color-hub-2` = `#6d8ad3` (heller),
|
|
was richtig ist (Hover = noch heller als Default-Button). Override bleibt
|
|
via Variable korrekt, kein Eingriff nötig.
|
|
- Button-Shadows: `rgba(26, 37, 64, …)` ist Light-Mode-spezifisch. Im Dark
|
|
Mode wirkt der bläuliche Shadow auf dunklem Card-BG falsch. Lösung:
|
|
per `@media (prefers-color-scheme: dark)` ODER `.dark`-Selektor die
|
|
Shadow-Farben auf transparenten Schwarz tönen.
|
|
|
|
### 3. `shared/hub-components.css`
|
|
|
|
- Bernstein-Stellen umstellen: `var(--color-accent)` →
|
|
`var(--color-accent-warm)` für **Hint-Card-Border-Left** und
|
|
**Progress-Bar-Fill** (sonst wird's im Portal Hub-Blau gemapt).
|
|
- Wegen Tokens-Architektur (`hub-soft` etc. werden im Dark Mode dunkler)
|
|
funktioniert der Großteil **automatisch** — keine `.dark`-Overrides nötig.
|
|
- Eine Ausnahme: `.panel-dark` und die Brand-Bridge-Boxes — im Light Mode
|
|
ist `panel-dark` Hub-Blau (#1a2540). Im Dark Mode bleibt das auch
|
|
`var(--color-hub)` — und da ist `--color-hub` heller (#5a78c2). Wir
|
|
brauchen also einen **konstanten dunklen Token** für `panel-dark` — sonst
|
|
wird die „dunkle“ Bridge-Card im Dark Mode plötzlich hellblau.
|
|
→ Neuer Token `--color-panel-dark` (immer #0f1729, in beiden Modi)
|
|
oder direkt `var(--color-topbar-deep)` (existiert bereits).
|
|
|
|
### 4. User-Menü-Switcher
|
|
|
|
Beide Dropdowns (Desktop in `sidebar.blade.php`, Mobile in derselben Datei)
|
|
bekommen vor dem Logout einen Block:
|
|
|
|
```blade
|
|
<flux:menu.separator />
|
|
<div class="px-2 py-1.5">
|
|
<flux:radio.group x-data variant="segmented" x-model="$flux.appearance" size="sm">
|
|
<flux:radio value="light" icon="sun" />
|
|
<flux:radio value="dark" icon="moon" />
|
|
<flux:radio value="system" icon="computer-desktop" />
|
|
</flux:radio.group>
|
|
</div>
|
|
```
|
|
|
|
Das ist exakt das Pattern aus `livewire/settings/appearance.blade.php`, nur
|
|
kompakt mit Icons-only. `$flux.appearance` ist FluxUI's Magic-Object,
|
|
LocalStorage-persistent, von `@fluxAppearance` injiziert.
|
|
|
|
### 5. Hub-Auth bleibt Light
|
|
|
|
`auth/pressekonto.blade.php` lädt **kein** `@fluxAppearance` und **kein**
|
|
`partials/head` — die Hub-Auth-Pipeline ist eigenständig. Damit wird `class="dark"`
|
|
dort nie gesetzt, selbst wenn das LocalStorage `dark` enthält. Hub-Auth bleibt
|
|
also automatisch Light. **Kein Eingriff nötig.**
|
|
|
|
---
|
|
|
|
## Implementierungs-Schritte (Reihenfolge)
|
|
|
|
1. `design-tokens.css`: Dark-Block aktivieren, `--color-accent-warm` definieren,
|
|
`--color-panel-dark` einführen (oder Re-Use `--color-topbar-deep`).
|
|
2. `portal.css`: Hack rausnehmen, Button-Shadow für Dark Mode tönen.
|
|
3. `hub-components.css`: Bernstein-Stellen auf `--color-accent-warm`,
|
|
`.panel-dark` auf `--color-panel-dark`.
|
|
4. `sidebar.blade.php`: Switcher in beide Dropdowns einbauen.
|
|
5. Build + Smoke-Test im Browser.
|
|
6. Bestehende Tests laufen lassen (sollten alle weiter grün sein, weil
|
|
keine Test-Assertion farbbezogen ist).
|
|
7. Pint + PROGRESS + Plan-Status.
|
|
|
|
## Akzeptanzkriterien
|
|
|
|
- [x] Plan-Dokument geschrieben
|
|
- [x] Switcher Light/Dark/System im User-Menü (Desktop + Mobile) sichtbar,
|
|
Änderung wirkt sofort + persistent (LocalStorage)
|
|
- [x] Dark Mode: Customer-Dashboard rendert mit allen Sektionen korrekt
|
|
(Tokens schalten um, kein hellblauer Akzent-Bug)
|
|
- [x] Brand-Bridge-Karte bleibt im Dark Mode dunkel (`--color-panel-dark-2`
|
|
konstant in beiden Modi)
|
|
- [x] Hub-Auth bleibt im Dark Mode Light (lädt kein `@fluxAppearance`)
|
|
- [x] Tests grün (18/18)
|
|
- [x] Pint clean
|
|
- [x] PROGRESS-Eintrag
|
|
|
|
## Risiken & Mitigation
|
|
|
|
- **FluxUI-Default-Komponenten im Dark Mode** (z.B. Modals, Dropdowns):
|
|
unsere Zinc→Hub-Mapping in `portal.css` bridgt die Skala. Im Dark Mode
|
|
müssen die Zinc-Werte auch umgekippt werden — passiert automatisch über
|
|
die Token-Vars, weil wir `var(--color-bg-*)` nutzen. Restrisiko: einzelne
|
|
FluxUI-Komponenten könnten harte Tailwind-Klassen wie `bg-white` haben,
|
|
die im Dark unverändert weiß bleiben. Smoke-Test deckt das auf.
|
|
- **Hub-Components-Schatten** sind in Hub-Blau-Alpha definiert
|
|
(`rgba(26, 37, 64, …)`). Im Dark Mode auf dunklem Bg wirken sie evtl.
|
|
„falsch warm“. Akzeptabel im ersten Wurf; Feintuning per `prefers-color-scheme`
|
|
Media-Query falls visuell stört.
|