diff --git a/.planning/STATE.md b/.planning/STATE.md index cf3e9d5..81b0faf 100644 --- a/.planning/STATE.md +++ b/.planning/STATE.md @@ -433,6 +433,7 @@ Gerettet aus `.continue-here.md`. Relevant fuer die noch offenen Live-Tests. | 260917-fast | **Desktop-Client: Startseite + Bau-Parallelitaet (Schnellkorrektur nach Bedienprobe).** Fenster "main" hatte keine Startseite -> "asset not found: index.html" (Altlast Phase 6); `"url": "setup.html"` in tauri.conf.json, per `strings` im Release-Binary bewiesen. `CARGO_BUILD_JOBS=4` im CI-Job desktop (8 rustc-Prozesse brachten den gemeinsam genutzten Host mit 15 GB an die Grenze), Betriebshandbuch Kap. 10, Befund in 18-UAT.md. | 2026-09-17 | b6d9013 | — | | 260917-e15 | **Desktop-Client-Icon: T statt "1".** Die fuenf Icon-Dateien in `apps/desktop/src-tauri/icons/` waren mit ImageMagicks internem MSVG-Renderer erzeugt, der `transform="rotate(12 51 21)"` nicht rendert -> gedrehte gelbe Kachel fehlte, App-Symbol sah aus wie eine "1". Satz mit `tauri icon` (resvg) aus `apps/web/src/app/icon.svg` neu erzeugt (nur die fuenf Dateien aus `bundle.icon`, kein icns/android/ios), Pixel-Gate an der Kachelmitte `FFED00FF`, icon.ico 16/24/32/48/64/256. Changelog. Nebenbefund: Erststart-Seite (Inline-SVG im WebView) war nie betroffen. | 2026-09-17 | 16564f4,6bb92dc | [260917-e15-desktop-client-icon-fehlende-gedrehte-ge](./quick/260917-e15-desktop-client-icon-fehlende-gedrehte-ge/) | | 260917-eta | **Desktop-Client: Tray „Beenden" beendete die App nicht; „Öffnen"/Linksklick holten minimiertes Fenster nicht zurueck.** Auf der Windows-Test-VM reproduziert (tasklist: `tessera-desktop.exe` lief nach „Beenden" weiter; Autostart-Haken im selben Menue funktionierte -> Klick kam an). Ursache: `app.run`-Handler rief bei jedem `RunEvent::ExitRequested` `api.prevent_exit()` — auch fuer `app.exit(0)` aus dem Tray. Fix: Muster `ExitRequested { code: None, api, .. }` (Tauri 2.11.3: `code` None = Nutzer-Interaktion, Some = programmatisch). Dazu `w.unminimize()` vor `show()` in „open" und im Linksklick-Handler (nach Win+D bewirkte „Öffnen" nichts). cargo check/clippy 0 Warnungen, rustfmt (9cb9d2e). Changelog 2 Stichpunkte. | 2026-09-17 | 68a69c6,9ba7456,9cb9d2e | [260917-eta-desktop-client-tray-eintrag-beenden-been](./quick/260917-eta-desktop-client-tray-eintrag-beenden-been/) | +| 260917-gsh | **Akzentfarbe als Hex-Code eingebbar; Bildmarke uebernimmt die Akzentfarbe.** `normalizeHexColor()` in `lib/color.ts` (optionales `#`, 3-stellige Kurzform, Kleinschreibung; 9 Tests), Textfeld neben dem Farbwaehler mit Zwei-Wege-Sync, `aria-invalid` + Fehlertext + gesperrtes Speichern bei ungueltigem Wert (7 Komponententests), i18n `settings.account.accentColorHex/-Invalid`. Gedrehte Kachel in `LogoMark` per Inline-Style `fill: var(--primary, #ffed00)` — folgt `applyAccentColor`, Anmeldeseite bleibt gelb. Tests Web 365 -> 381 / 57 Dateien, tsc 0. | 2026-09-17 | 795c6a4,1601d97,db478e0 | [260917-gsh-akzentfarbe-in-einstellungen-konto-zusae](./quick/260917-gsh-akzentfarbe-in-einstellungen-konto-zusae/) | ## Deferred Items diff --git a/.planning/quick/260917-gsh-akzentfarbe-in-einstellungen-konto-zusae/260917-gsh-SUMMARY.md b/.planning/quick/260917-gsh-akzentfarbe-in-einstellungen-konto-zusae/260917-gsh-SUMMARY.md new file mode 100644 index 0000000..95dd0af --- /dev/null +++ b/.planning/quick/260917-gsh-akzentfarbe-in-einstellungen-konto-zusae/260917-gsh-SUMMARY.md @@ -0,0 +1,150 @@ +--- +phase: quick-260917-gsh +plan: 01 +subsystem: ui +tags: [react, nextjs, tailwind, vitest, next-intl, svg, css-custom-properties] + +requires: [] +provides: + - "normalizeHexColor() (apps/web/src/lib/color.ts) — reine Funktion, normalisiert Hex-Farbeingaben auf #rrggbb" + - "Einstellungen → Konto: Hex-Textfeld neben dem Akzentfarb-Waehler, bidirektional synchron" + - "LogoMark: gedrehte Signalkachel folgt der persoenlichen Akzentfarbe (--primary) statt fester gelber Fuellung" +affects: [settings, brand, i18n] + +actuals: + tokens: 5987 + tasks: 3 + commits: 3 + plan_head_before: f6eda20 + +tech-stack: + added: [] + patterns: + - "SVG-Praesentationsattribute (fill=...) loesen var() nicht zuverlaessig auf; Inline-Style (style={{ fill: 'var(--token, fallback)' }}) tut es" + +key-files: + created: + - apps/web/src/lib/color.ts + - apps/web/src/lib/color.test.ts + - apps/web/src/components/settings/account-settings-form.test.tsx + modified: + - apps/web/src/components/settings/account-settings-form.tsx + - apps/web/src/messages/de.json + - apps/web/src/messages/en.json + - apps/web/src/components/brand/tessera-logo.tsx + - apps/web/src/components/brand/tessera-logo.test.tsx + - apps/web/src/components/brand/brand.ts + - CHANGELOG.md + +key-decisions: + - "onBlur des Hex-Textfelds normalisiert auf die kanonische Form (Kleinbuchstaben, expandierte Kurzform) statt den Rohtext stehen zu lassen — damit bleibt z. B. FFED00 nicht dauerhaft in Grossbuchstaben im Feld." + - "accentColor (Farbwaehler-Zustand) bleibt die einzige Quelle, die je an und die Speichern-Action geht; der Rohtext lebt getrennt in hexInput, damit ein ungueltiger Zwischenstand nie auf #000000 zurueckfallen laesst." + - "Bildmarke: Inline-Style statt fill-Attribut, weil jsdom/Browser var() in SVG-Praesentationsattributen nicht zuverlaessig aufloesen; BRAND_YELLOW bleibt als textueller Rueckfallwert im Style-String erhalten." + +patterns-established: + - "Formular-Sync zwischen einer strukturierten Eingabe (color-Picker) und einer Freitext-Alternative: getrennter Rohtext-Zustand + abgeleitete Gueltigkeit, kanonischer Wert wird nur bei Gueltigkeit in den strukturierten Zustand uebernommen." + +requirements-completed: [QUICK-260917-GSH] + +coverage: + - id: D1 + description: "Hex-Textfeld neben dem Farbwaehler, vorbelegt, normalisiert Eingaben, synchron mit dem Farbwaehler in beide Richtungen, Fehlerzustand + Speichersperre bei ungueltigem Wert, Reset setzt beides zurueck" + requirement: "QUICK-260917-GSH" + verification: + - kind: unit + ref: "apps/web/src/components/settings/account-settings-form.test.tsx#AccountSettingsForm — Akzentfarbe Hex-Eingabe (7 Tests)" + status: pass + human_judgment: true + rationale: "Visuelle/funktionale Bedienprobe im Browser (Farbwaehler-Reaktion, roter Rand, Speichern-Sperre) ist laut Plan Aufgabe des Orchestrators, nicht Teil dieses Plans." + - id: D2 + description: "normalizeHexColor() als reine Funktion mit neun Testfaellen (gueltig/ungueltig, Kurzform, Leerraum, Gross-/Kleinschreibung)" + requirement: "QUICK-260917-GSH" + verification: + - kind: unit + ref: "apps/web/src/lib/color.test.ts#normalizeHexColor (9 Tests)" + status: pass + human_judgment: false + - id: D3 + description: "Gedrehte Signalkachel der Bildmarke folgt der Akzentfarbe (--primary) mit Markengelb als Rueckfall; vier Olivkacheln und Grundplatte unveraendert" + requirement: "QUICK-260917-GSH" + verification: + - kind: unit + ref: "apps/web/src/components/brand/tessera-logo.test.tsx#renders exactly five tiles; only the rotated one is filled from the accent token with the brand yellow as fallback" + status: pass + human_judgment: true + rationale: "Sichtbarer Farbwechsel in Kopfzeile/Seitenleiste/Anmeldeseite ist eine visuelle Bedienprobe im Browser — laut Plan Aufgabe des Orchestrators, nicht Teil dieses Plans." + +duration: ~20min +completed: 2026-09-17 +status: complete +--- + +# Quick Task 260917-gsh: Akzentfarbe — Hex-Eingabe und Bildmarke in Akzentfarbe Summary + +**Hex-Textfeld neben dem Akzentfarb-Waehler (normalizeHexColor() als reine Funktion) plus gedrehte Logokachel, die per `var(--primary, BRAND_YELLOW)` der persoenlichen Akzentfarbe folgt** + +## Performance + +- **Duration:** ~20 min +- **Completed:** 2026-09-17T10:16:32Z +- **Tasks:** 3/3 +- **Files modified:** 10 (3 neu, 7 geaendert) + +## Accomplishments +- `normalizeHexColor()` (apps/web/src/lib/color.ts) normalisiert Hex-Eingaben (fuehrendes `#` optional, 3-stellige Kurzform expandiert, Leerraum getrimmt, kleingeschrieben) — 9 Testfaelle gruen +- Kontoformular: Hex-Textfeld ersetzt den reinen Anzeige-``, bidirektional synchron mit dem Farbwaehler, Fehlerzustand (`aria-invalid`, roter Rand, Fehlertext) sperrt „Farbe speichern" +- `LogoMark` (Bildmarke): gedrehte Signalkachel per Inline-Style `fill: var(--primary, #ffed00)` statt festem `fill`-Attribut — folgt jetzt der Akzentfarbe in Kopfzeile, Seitenleiste und leerem Dashboard, Markengelb bleibt Rueckfall vor der Anmeldung +- i18n de/en vollstaendig (`settings.account.accentColorHex`, `accentColorHexInvalid`), CHANGELOG mit zwei Stichpunkten + +## Task Commits + +Each task was committed atomically: + +1. **Task 1: Hex-Eingabe — Normalisierung, Formular-Sync, i18n, Tests** - `795c6a4` (feat) +2. **Task 2: Bildmarke — gedrehte Kachel in Akzentfarbe, Test und Kommentare** - `1601d97` (feat) +3. **Task 3: CHANGELOG — zwei Stichpunkte, Gesamtlauf** - `db478e0` (docs) + +**Plan metadata:** wird vom Orchestrator nach diesem SUMMARY committet. + +_Task 1 (`type="tracer" tdd="true"`) und Task 2 (`tdd="true"`) folgten RED→GREEN: Testdateien zuerst angelegt und rot gesehen (fehlendes Modul bzw. fehlender Inline-Style), dann die Implementierung ergaenzt._ + +## Files Created/Modified +- `apps/web/src/lib/color.ts` - `normalizeHexColor(input): string | null`, reine Funktion, keine Abhaengigkeiten +- `apps/web/src/lib/color.test.ts` - 9 Testfaelle (gueltig/ungueltig, Kurzform, Leerraum, Gross-/Kleinschreibung) +- `apps/web/src/components/settings/account-settings-form.tsx` - Hex-Textfeld, `hexInput`-Zustand, Sync mit Farbwaehler, Speichern-Sperre bei ungueltigem Text +- `apps/web/src/components/settings/account-settings-form.test.tsx` - 7 Testfaelle (Vorbelegung, Sync in beide Richtungen, Fehlerzustand, Blur-Normalisierung, Reset, Speichern) +- `apps/web/src/messages/de.json`, `en.json` - `settings.account.accentColorHex`, `accentColorHexInvalid` +- `apps/web/src/components/brand/tessera-logo.tsx` - gedrehte Kachel mit `style={{ fill: 'var(--primary, ...)' }}`, JSDoc-Ergaenzung, deutscher Kommentar zur Begruendung +- `apps/web/src/components/brand/tessera-logo.test.tsx` - Kacheltest umgeschrieben (Inline-Style-Fuellung statt `fill`-Attribut) +- `apps/web/src/components/brand/brand.ts` - Kommentar zu `BRAND_YELLOW` als Rueckfallwert +- `CHANGELOG.md` - je ein Stichpunkt unter „Neu" und „Geändert" + +## Decisions Made +- onBlur des Hex-Textfelds normalisiert auf die kanonische Form (Kleinbuchstaben, expandierte Kurzform) — Ermessensentscheidung des Planers, uebernommen wie im Plan vorgesehen. +- `accentColor` bleibt die einzige Quelle fuer Farbwaehler und Speichern-Action; der Rohtext lebt getrennt in `hexInput`, damit ein ungueltiger Zwischenstand `` nie auf `#000000` zurueckfallen laesst. +- Inline-Style statt `fill`-Praesentationsattribut fuer die Logokachel, weil `var()` in SVG-Praesentationsattributen nicht zuverlaessig aufgeloest wird. + +## Deviations from Plan + +None - plan executed exactly as written. + +## Issues Encountered + +None. + +## User Setup Required + +None - no external service configuration required. + +## Next Phase Readiness + +- Browser-Nachweis (Orchestrator, nicht Teil dieses Plans): Einstellungen → Konto, `FFED00`/`#fe0` tippen → Farbwaehler folgt; `#ggg` → roter Rand, Speichern gesperrt; Farbe speichern → Kachel der Bildmarke wechselt sofort; Zuruecksetzen → gelb; Anmeldeseite nach Abmelden → Kachel gelb. +- Kein Blocker fuer weitere Arbeit — Formular- und Bildmarken-Tests laufen unveraendert weiter mit dem restlichen Web-Testlauf (381/381 gruen, Typpruefung sauber). + +--- +*Quick Task: 260917-gsh* +*Completed: 2026-09-17* + +## Self-Check: PASSED + +All 11 claimed files found on disk; all 3 task commits (795c6a4, 1601d97, db478e0) found in git history.