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

14 KiB
Raw Permalink Blame History

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:

// 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:

// 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:

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)

cd docker/ui
npm ci                 # einmalig
npm run build          # MUSS grün sein — das prüft auch die Ampel

Lokal ansehen (Dev-Server):

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.