Files
rippy/docs/DESIGN-2.0-BRIEFING.md
Hitonabi b8162753a9
Ampel / ampel (push) Successful in 27s
chore: Single Source of Truth = main (stable-Branch + Gruen-Gate abgeschafft)
Commander-Entscheid 24.07.: nur noch EIN Branch. Der stable-Zwischenbranch
war vestigial — die VM deployt ohnehin aus main (git pull), das Gruen-Gate
hat den Live-Deploy nie real gegated.

- ci.yml: Beförderungs-Schritt (push -> stable) entfernt; die Ampel prueft
  nur noch (Ruff/pytest/Vite-Build), Rot heisst weiterhin: nicht deployen.
- deploy.sh: klont/resettet auf main statt stable.
- AGENTS §C, README (Entwicklung), DESIGN-2.0-Briefing: auf main-only
  umgeschrieben. Design-2.0-Briefing als ERLEDIGT markiert.
- SAVEPOINT v3.6.

Branches stable / design-2.0 / kernumbau-2026-07-23 werden nach diesem
Push geloescht (Inhalte vollstaendig in main).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-24 16:13:10 +02:00

302 lines
14 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Design 2.0 — Briefing (Übergabe an Gemini)
> ✅ **ERLEDIGT (24.07.2026).** Design 2.0 wurde umgesetzt und ist in `main`.
> Der Arbeitsbranch `design-2.0` wurde nach dem Merge gelöscht (es gibt nur
> noch `main`). Dieses Dokument bleibt als historische Auftragsbeschreibung.
>
> Dieses Dokument ist die vollständige Auftragsbeschreibung für den UI-Umbau
> „Design 2.0". Es ist so geschrieben, dass ein zweites KI-Modell (Gemini)
> eigenständig loslegen kann. Stand: 24.07.2026, vorbereitet von Claude.
---
## 0. Auftrag in einem Satz
Das Rippy-Web-UI von 428 handgeschriebenen `theme === 'dark' ? … : …`-
Ternaries auf ein **sauberes, token-basiertes Tailwind-`dark:`-System**
umstellen und dabei die Optik auf ein modernes, konsistentes „Design 2.0"
heben — **ohne** Funktion, API-Aufrufe, deutsche Texte oder die
Deploy-Kette anzufassen.
---
## 1. Was Rippy ist (Kontext in 30 Sekunden)
Rippy ist eine self-hosted Disc-Ripping-Maschine (CD/DVD/Blu-ray/4K-UHD):
Disc rein → automatisch erkannt → verlustfrei gerippt (MakeMKV) →
komprimiert (HandBrake) → Media-Server-fertig abgelegt. Alles Docker,
alles im Heimnetz. Das UI ist die einzige Bedienoberfläche.
**Tech-Stack UI** (`docker/ui/`):
- React 18 + TypeScript + Vite
- TailwindCSS (`darkMode: 'class'`)
- lucide-react (Icons)
- Kein Router (Seitenwechsel über `useState` in `App.tsx`)
- State: lokale Hooks + Polling gegen die REST-API (`src/lib/api.ts`,
axios, `baseURL: '/api'`)
**Sprach-Konvention (AGENTS.md Regel 4):** Variablen-/Funktionsnamen auf
Englisch, **alle Kommentare, UI-Texte und Docs auf Deutsch**. Der Betreiber
(„Commander") ist Nicht-Entwickler und liest alles.
---
## 2. Der Kern des Problems
Jede Komponente entscheidet Farben **zur Laufzeit per Ternary**:
```tsx
// SO sieht es HEUTE ~428× aus:
<div className={`rounded-xl border ${theme === 'dark'
? 'bg-slate-800 border-slate-700'
: 'bg-white border-slate-200'}`}>
```
Das ist der größte technische Schuldenberg des UI:
- **428 Ternaries** in 18 Dateien (Inventar unten) — jede Farbe doppelt
gepflegt, Copy-Paste-Fehler vorprogrammiert.
- Jede Komponente zieht dafür `const { theme } = useDarkMode()` — Rendering
hängt an einem Context-Wert, den es fast nie bräuchte.
- Wiederkehrende Farb-Mappings sind **mehrfach dupliziert** statt zentral:
`StatusBadge` (Dashboard), `getLevelColor` (Logs), `getTypeColor`
(DeviceDiscovery) definieren jeweils eigene Status→Farbe-Tabellen.
### Warum das JETZT ein leichter Umbau ist
Die Infrastruktur für den sauberen Weg **steht bereits vollständig**:
- `tailwind.config.js`: `darkMode: 'class'`
- `ThemeContext.tsx` setzt beim Umschalten `document.documentElement.
classList.add('dark')` — also `.dark` auf `<html>` ✅
- Damit funktionieren Tailwinds `dark:`-Varianten sofort überall.
Konkret heißt Migration also fast immer nur:
```tsx
// NACHHER — kein Ternary, kein useDarkMode nötig:
<div className="rounded-xl border bg-white border-slate-200
dark:bg-slate-800 dark:border-slate-700">
```
### Drei Altlasten, die mit aufgeräumt werden sollten
1. **Tote CSS-Variablen** (`src/index.css`): Es gibt `:root { --bg-color … }`
und `[data-theme="dark"] { … }`. Der Dark-Block ist **toter Code** —
nichts setzt jemals `data-theme` (der Theme-Umschalter nutzt die
`.dark`-Klasse). Entweder die Variablen korrekt an `.dark` binden ODER
(empfohlen) ganz auf Tailwind-`dark:` setzen und die Variablen entfernen.
2. **Globale Transition** (`src/index.css`): `* { transition:
background-color .3s, color .3s, border-color .3s; }` lässt bei jedem
Theme-Wechsel die GESAMTE Seite animieren (Jank-Risiko) und macht die
überall verstreuten `transition-colors duration-300`-Klassen doppelt.
Auf einen bewussten, schmalen Transition-Ansatz reduzieren.
3. **Icon-Inkonsistenz**: Fast alles nutzt `lucide-react`, aber
`ConfirmDialog.tsx` nutzt Emoji (⚠️✅🤔) als „Icons". Vereinheitlichen.
---
## 3. Empfohlener Weg (technisch)
**Nicht** blind 428 Ternaries per Hand ersetzen — das ist fehleranfällig.
Stattdessen in zwei Schichten:
### Schicht A — Wiederverwendbare Primitives (`src/components/ui/`)
Ein kleines Set typisierter Bausteine, die das Design kapseln. Heute wird
jedes davon in jeder Datei neu zusammengeklöppelt:
- `Card` / `CardHeader` — die `rounded-xl border bg-white dark:bg-slate-800`-
Kachel (kommt ~30× vor)
- `Button` (Varianten: primary / secondary / ghost / danger)
- `Badge` (Status/Typ-Pill mit zentraler Farbtabelle — löst die 3 Duplikate)
- `Input` / `Select` / `Toggle` (Formularfelder, heute inline-dupliziert)
- `Modal` (der `fixed inset-0 … backdrop-blur`-Rahmen — 4× dupliziert:
RipTargetModal, JobDetailModal, MetadataKorrektur, ConfirmDialog)
- `Section` / `PageHeader` (Seiten-Titel + Untertitel, überall gleich)
Farbwelt/Status **einmal zentral** definieren (z. B.
`src/lib/design.ts`), damit Status→Farbe nur an EINER Stelle lebt:
```ts
export const STATUS_STYLES = {
pending: 'bg-amber-100 text-amber-700 dark:bg-amber-900/30 dark:text-amber-400',
processing: 'bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-400',
transcoding: 'bg-purple-100 text-purple-700 dark:bg-purple-900/30 dark:text-purple-400',
completed: 'bg-emerald-100 text-emerald-700 dark:bg-emerald-900/30 dark:text-emerald-400',
failed: 'bg-rose-100 text-rose-700 dark:bg-rose-900/30 dark:text-rose-400',
// Disc-Typen: cd=blue, dvd=purple, bluray=pink, uhd=amber
} as const
```
### Schicht B — Seiten/Komponenten auf die Primitives umstellen
Datei für Datei die Ternaries durch `dark:`-Klassen bzw. die neuen
Primitives ersetzen. `const { theme } = useDarkMode()` fällt dabei in
fast allen Dateien weg (nur `App.tsx` braucht `toggleTheme` noch).
### Optional als echtes „2.0": Tailwind-Theme-Tokens
Statt roher `slate-*`/`indigo-*`-Klassen semantische Tokens in
`tailwind.config.js` (`theme.extend.colors`) definieren
(`surface`, `surface-muted`, `border-subtle`, `accent`, `text-primary`,
`text-muted` …) und diese nutzen. Das macht spätere Farb-Anpassungen zu
einer Ein-Zeilen-Änderung. **Kür, kein Muss** — die `dark:`-Umstellung
ist der Pflichtteil.
---
## 4. Design-Richtung (Leitplanken, nicht Korsett)
Die bestehende Farbwelt ist bereits kohärent — bitte **systematisieren und
verfeinern, nicht wild neu erfinden**. Referenz aus dem Ist-Zustand:
- **Akzent/Primär:** Indigo (`indigo-600`), Verlauf `indigo-500 → purple-600`
(Logo, Buttons, aktive Nav)
- **Flächen:** hell `slate-50` (Seite) / `white` (Karten); dunkel
`slate-950`/`slate-900` (Seite) / `slate-800` (Karten)
- **Ränder:** `slate-200` hell / `slate-700` dunkel
- **Status:** amber=wartend/Warnung, blue=Bearbeitung/Info,
purple=Komprimieren, emerald=fertig/Erfolg, rose=Fehler; Disc-Typen:
cd=blue, dvd=purple, bluray=pink, **uhd=amber** (bewusst abgesetzt)
- **Typo:** system-sans (siehe `index.css`), Überschriften `font-bold`
**Spielraum für 2.0** (gern, solange konsistent + zugänglich):
Abstände/Rhythmus vereinheitlichen, Karten-Schatten/Radien harmonisieren,
Empty-States aufwerten, Fokus-/Hover-Zustände konsistent, bessere
Dichte in den Tabellen, der neue **Anleitung**-Tab (`pages/Anleitung.tsx`)
darf visuell aufgewertet werden. Barrierefreiheit im Blick behalten
(Kontrast, Fokus-Ringe, `aria-*` wo sinnvoll).
Es gibt eine `Skill`/Guideline „Web Interface Guidelines" — an modernen
Best-Practices orientieren.
---
## 5. HARTE Regeln (nicht verhandelbar)
1. **Nur UI, nur `docker/ui/src/`** (+ ggf. `tailwind.config.js`,
`index.css`, `index.html`). **Kein** Backend (`docker/api`,
`docker/worker`), **keine** API-Verträge, **keine** `docker-compose.yml`.
2. **Funktion bleibt 1:1.** Alle bestehenden Features, Flows, API-Calls,
Polling-Intervalle, Feldnamen im POST-Body bleiben exakt erhalten. Das
ist ein **Re-Skin + Refactor**, kein Feature-Umbau. Im Zweifel:
Verhalten unverändert lassen.
3. **Deutsch bleibt Deutsch.** Kein UI-Text wird übersetzt oder
umformuliert (außer offensichtliche Tippfehler). Kommentare Deutsch.
4. **Die CI-Ampel MUSS grün bleiben** (`.gitea/workflows/ci.yml`): bei
jedem Push laufen Ruff, pytest UND `npm run build` (Vite). Ein
TypeScript-/Build-Fehler = rot = nicht fertig. Nach JEDER umgestellten
Komponente lokal `npm run build` grün halten.
5. **`package-lock.json` committen**, falls neue Abhängigkeiten dazukommen
(die Ampel prüft Reproduzierbarkeit). Neue Runtime-Deps sparsam — das
Ziel ist weniger Code, nicht mehr.
6. **AGENTS.md gelesen halten** (Repo-Wurzel) — die dortigen Regeln gelten.
---
## 6. Datei-Inventar (Fahrplan, Stand 24.07.2026)
Sortiert nach Aufwand. Zahlen = `theme === 'dark'`-Ternaries in der Datei.
| Datei | Zeilen | Ternaries | Hinweis |
|---|---:|---:|---|
| `pages/Settings.tsx` | 860 | **128** | Größter Brocken; viele Tabs — evtl. in Unterkomponenten pro Tab zerlegen |
| `pages/Dashboard.tsx` | 504 | 44 | Enthält `StatusBadge`/`TypeBadge`/`ProgressBar`/`StatCard` → in Primitives heben |
| `components/DeviceDiscovery.tsx` | 381 | 43 | Disc-Karte + Laufwerks-Liste; `getTypeColor`/`getStatusColor` zentralisieren |
| `components/RipTargetModal.tsx` | 401 | 37 | Modal + Track-Tabelle + Serien-Felder |
| `pages/Logs.tsx` | 246 | 34 | `getLevelColor`/`getLevelIcon`/`getLevelLabel` → zentral |
| `components/StorageMounts.tsx` | 361 | 33 | Mounts + Ordner-Browser |
| `components/JobDetailModal.tsx` | 239 | 28 | Modal, Download-Liste |
| `components/FirstRunWizard.tsx` | 192 | 22 | Onboarding |
| `components/WorkerVerwaltung.tsx` | 214 | 18 | Worker-Liste + Anbinde-Befehle |
| `components/LiveLogSection.tsx` | 147 | 15 | Live-Log-Kachel |
| `components/MetadataKorrektur.tsx` | 145 | 10 | Korrektur-Popup |
| `pages/Anleitung.tsx` | 180 | 7 | Neu; darf visuell aufgewertet werden |
| `components/ConfirmDialog.tsx` | 83 | 6 | Emoji-Icons → lucide |
| `App.tsx` | 101 | 2 | Sidebar/Nav/Footer; behält `toggleTheme` |
| `context/ThemeContext.tsx` | 52 | 1 | Bleibt im Kern; ggf. `data-theme` synchron setzen, falls CSS-Variablen genutzt werden |
| `context/ToastContext.tsx` | 62 | 0 | Nutzt schon `dark:` teils — als Vorbild ansehen |
**Gesamt: 428 Ternaries.** Bereits `dark:`-Klassen im Code: nur 7 —
d. h. `ToastContext` und Reste zeigen das Zielbild.
**Empfohlene Reihenfolge:** erst Schicht A (Primitives + `design.ts`),
dann die kleinen Dateien (`ConfirmDialog`, `App`, `LiveLogSection`) als
Kalibrierung, dann die großen. `Settings.tsx` zuletzt (größter Nutzen aus
den dann fertigen Primitives).
---
## 7. Arbeitsweise & Branch
- **Auf einem eigenen Branch arbeiten** (war: `design-2.0`). Ein
Feature-Branch lässt die Ampel laufen (Feedback grün/rot), deployt aber
nicht — ideal für einen großen Umbau; nach Abnahme nach `main` gemerged.
(Hinweis: Seit 24.07.2026 ist `main` der einzige Branch — deployt wird
direkt daraus, die Ampel prüft nur noch.)
- **Klein committen**, eine sinnvolle Einheit pro Commit (z. B. „Primitives:
Card + Button", dann „Dashboard auf Primitives umgestellt"). Commit-Text
Deutsch, WAS + WARUM.
- **Nach jeder Komponente**: `npm run build` muss grün sein. Nie einen
roten Zwischenstand pushen.
- Visuell gegenprüfen: hell UND dunkel testen (Theme-Umschalter oben in der
Sidebar).
---
## 8. Verifikation (die exakten Befehle)
```bash
cd docker/ui
npm ci # einmalig
npm run build # MUSS grün sein — das prüft auch die Ampel
```
Lokal ansehen (Dev-Server):
```bash
cd docker/ui && npm run dev
```
Das UI erwartet die API unter `/api` (nginx-Proxy). Für reine Design-
Arbeit reicht der Dev-Server; leere Listen/Fehlerzustände sind normal ohne
laufendes Backend. Wer gegen echte Daten testen will: Das Live-System läuft
im Heimnetz (Zugang beim Commander erfragen).
Die **komplette** Ampel (wie in CI) prüft zusätzlich Backend-Tests — die
sind von reiner UI-Arbeit nicht betroffen, müssen aber grün bleiben (nicht
anfassen).
---
## 9. Definition of Done
- [ ] `src/components/ui/`-Primitives existieren und werden genutzt
- [ ] Status/Typ/Level-Farben zentral (`src/lib/design.ts`), keine
duplizierten Farb-Mappings mehr
- [ ] `grep -rn "theme === 'dark'" src/` ergibt **~0** Treffer (idealerweise
nur noch in `ThemeContext`/`App` das Nötigste)
- [ ] Tote CSS-Variablen (`[data-theme="dark"]`) und globale `* {
transition }` bereinigt
- [ ] `ConfirmDialog` nutzt lucide statt Emoji
- [ ] Hell- UND Dunkelmodus überall konsistent, keine „weiße Karte im
Darkmode"-Ausrutscher
- [ ] `npm run build` grün; keine neuen TS-Fehler/Warnungen
- [ ] Keine funktionale Änderung (alle API-Calls/Flows identisch)
- [ ] Alle deutschen Texte unverändert
- [ ] Auf Branch `design-2.0`, sauber committet, bereit für Review/Merge
---
## 10. Copy-Paste-Startprompt für Gemini
> Du übernimmst „Design 2.0" für das Rippy-Web-UI (React + TypeScript +
> Vite + TailwindCSS, `darkMode: 'class'`). Lies zuerst
> `docs/DESIGN-2.0-BRIEFING.md` KOMPLETT — dort stehen Auftrag, harte
> Regeln, Datei-Inventar, empfohlener Weg und die Definition of Done.
> Arbeite ausschließlich in `docker/ui/`, auf dem Branch `design-2.0`.
> Kernauftrag: 428 `theme === 'dark' ? …`-Ternaries durch Tailwind-`dark:`-
> Klassen + wiederverwendbare UI-Primitives ersetzen und die Optik
> modernisieren — OHNE Funktion, API-Aufrufe oder deutsche Texte zu ändern.
> Halte nach jeder umgestellten Komponente `npm run build` grün. Beginne
> mit den UI-Primitives (`src/components/ui/`) und `src/lib/design.ts`,
> dann die kleinen Dateien, dann die großen (`Settings.tsx` zuletzt).
> Kommentare und Commit-Texte auf Deutsch.