From 602ccce46e6fbe2bd0ae2a84286e27ba5ae0bd30 Mon Sep 17 00:00:00 2001 From: "Dennis (via Claude+Gemma)" Date: Sat, 23 May 2026 08:28:06 +0200 Subject: [PATCH] =?UTF-8?q?feat(custom-themes):=203=20Color-Themes=20w?= =?UTF-8?q?=C3=A4hlbar=20(Ember/Ocean/Forest)=20[tsc:fail]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .phase23-state.json | 7 +++++-- GENERATION_LOG.md | 19 +++++++++++++++++++ apps/web/src/index.css | 20 ++++++++++++++++++-- apps/web/src/lib/theme.tsx | 24 +++++++++++++++++++++++- 4 files changed, 65 insertions(+), 5 deletions(-) diff --git a/.phase23-state.json b/.phase23-state.json index 60db49c..8fece8a 100644 --- a/.phase23-state.json +++ b/.phase23-state.json @@ -1,5 +1,8 @@ { "completed_features": [], - "current_feature": "workspace-logo", - "started_at": "2026-05-23T08:25:49.746920" + "current_feature": "custom-themes", + "started_at": "2026-05-23T08:25:49.746920", + "attempted_features": [ + "workspace-logo" + ] } \ No newline at end of file diff --git a/GENERATION_LOG.md b/GENERATION_LOG.md index 0c3bf88..d2f6754 100644 --- a/GENERATION_LOG.md +++ b/GENERATION_LOG.md @@ -2706,3 +2706,22 @@ src/index.ts(27,25): error TS2769: No overload matches this call. Overload 2 of 3, '(plugin: FastifyPluginAsync<{ limits: { fileSize: number; }; }, RawServerDefault, FastifyTypeProvider, FastifyBaseLogger>, opts?: FastifyRegisterOptions<...> | undefined): FastifyInstance<...> & PromiseLike<...>', gave the following error. Argument of type 'Promise' is not assignable to parameter of type 'FastifyPluginAsync<{ limits: { fileSize: number; }; }, RawServerDefault, FastifyTypeProvider, FastifyBaseLogger>'. Type 'Promise' provides no match for the signature '(instance: FastifyInstance, FastifyBaseLogger, FastifyTy +- `08:27:37` **INFO** Committed feature workspace-logo +- `08:27:37` **INFO** Pushed: rc=0 + +## Phase-3 Feature: custom-themes (2026-05-23 08:27:37) + +- `08:27:37` **INFO** Description: 3 Color-Themes wählbar (Ember/Ocean/Forest) +- `08:27:37` **INFO** Generating apps/web/src/lib/theme.tsx (ERWEITERT — behalte light/dark toggle. Füge zusätzlich color-theme: 'e…) +- `08:27:55` **INFO** wrote 2163 chars in 17.9s (attempt 1) +- `08:27:55` **INFO** Generating apps/web/src/index.css (ERWEITERT — behalte alles. Füge CSS-vars für color-themes: html[data-c…) +- `08:28:04` **INFO** wrote 792 chars in 9.2s (attempt 1) +- `08:28:04` **INFO** Running tsc --noEmit on api… +- `08:28:06` **WARN** tsc errors: +src/index.ts(27,25): error TS2769: No overload matches this call. + Overload 1 of 3, '(plugin: FastifyPluginCallback<{ limits: { fileSize: number; }; }, RawServerDefault, FastifyTypeProvider, FastifyBaseLogger>, opts?: FastifyRegisterOptions<...> | undefined): FastifyInstance<...> & PromiseLike<...>', gave the following error. + Argument of type 'Promise' is not assignable to parameter of type 'FastifyPluginCallback<{ limits: { fileSize: number; }; }, RawServerDefault, FastifyTypeProvider, FastifyBaseLogger>'. + Type 'Promise' provides no match for the signature '(instance: FastifyInstance, FastifyBaseLogger, FastifyTypeProvider>, opts: { ...; }, done: (err?: Error | undefined) => void): void'. + Overload 2 of 3, '(plugin: FastifyPluginAsync<{ limits: { fileSize: number; }; }, RawServerDefault, FastifyTypeProvider, FastifyBaseLogger>, opts?: FastifyRegisterOptions<...> | undefined): FastifyInstance<...> & PromiseLike<...>', gave the following error. + Argument of type 'Promise' is not assignable to parameter of type 'FastifyPluginAsync<{ limits: { fileSize: number; }; }, RawServerDefault, FastifyTypeProvider, FastifyBaseLogger>'. + Type 'Promise' provides no match for the signature '(instance: FastifyInstance, FastifyBaseLogger, FastifyTy diff --git a/apps/web/src/index.css b/apps/web/src/index.css index 16843a0..4a5774c 100644 --- a/apps/web/src/index.css +++ b/apps/web/src/index.css @@ -2,6 +2,22 @@ @tailwind components; @tailwind utilities; +:root { + --primary: #f97316; +} + +html[data-color-theme='ember'] { + --primary: #f97316; +} + +html[data-color-theme='ocean'] { + --primary: #0ea5e9; +} + +html[data-color-theme='forest'] { + --primary: #10b981; +} + @layer base { * { @apply transition-colors duration-150; @@ -12,11 +28,11 @@ } button:focus-visible { - @apply outline-none ring-2 ring-ember-500 outline-offset-2; + @apply outline-none ring-2 ring-[var(--primary)] outline-offset-2; } input:focus { - @apply ring-2 ring-ember-500 border-ember-500 outline-none; + @apply ring-2 ring-[var(--primary)] border-[var(--primary)] outline-none; } } diff --git a/apps/web/src/lib/theme.tsx b/apps/web/src/lib/theme.tsx index 5b3ada9..09711ae 100644 --- a/apps/web/src/lib/theme.tsx +++ b/apps/web/src/lib/theme.tsx @@ -1,11 +1,14 @@ import { createContext, useContext, useEffect, useState } from 'react'; type Theme = 'light' | 'dark'; +type ColorTheme = 'ember' | 'ocean' | 'forest'; interface ThemeContextType { theme: Theme; setTheme: (theme: Theme) => void; toggleTheme: () => void; + colorTheme: ColorTheme; + setColorTheme: (colorTheme: ColorTheme) => void; } const ThemeContext = createContext(undefined); @@ -20,6 +23,15 @@ export function ThemeProvider({ children }: { children: React.ReactNode }) { return 'light'; }); + const [colorTheme, setColorThemeState] = useState(() => { + if (typeof window !== 'undefined') { + const saved = localStorage.getItem('colorTheme') as ColorTheme | null; + if (saved) return saved; + return 'ember'; + } + return 'ember'; + }); + useEffect(() => { const root = window.document.documentElement; if (theme === 'dark') { @@ -30,6 +42,12 @@ export function ThemeProvider({ children }: { children: React.ReactNode }) { localStorage.setItem('theme', theme); }, [theme]); + useEffect(() => { + const root = window.document.documentElement; + root.dataset.colorTheme = colorTheme; + localStorage.setItem('colorTheme', colorTheme); + }, [colorTheme]); + const setTheme = (newTheme: Theme) => { setThemeState(newTheme); }; @@ -38,8 +56,12 @@ export function ThemeProvider({ children }: { children: React.ReactNode }) { setThemeState((prev) => (prev === 'light' ? 'dark' : 'light')); }; + const setColorTheme = (newColorTheme: ColorTheme) => { + setColorThemeState(newColorTheme); + }; + return ( - + {children} );