From 6950deaa882a5a8ee26a570ede733e5e330a6cb8 Mon Sep 17 00:00:00 2001 From: Mike Freno Date: Thu, 5 Feb 2026 00:55:10 -0500 Subject: [PATCH] it is time --- src/components/PreferencesPanel.tsx | 37 ++++---- src/components/SourceManager.tsx | 23 ++--- src/context/ThemeContext.tsx | 25 +++-- src/utils/color.ts | 93 ------------------- .../theme-refactoring-01-create-schema.md | 63 +++++++++++++ .../theme-refactoring-02-convert-themes.md | 77 +++++++++++++++ .../theme-refactoring-03-update-types.md | 70 ++++++++++++++ .../theme-refactoring-04-theme-resolution.md | 83 +++++++++++++++++ .../theme-refactoring-05-theme-context.md | 80 ++++++++++++++++ .../theme-refactoring-06-theme-loader.md | 79 ++++++++++++++++ .../theme-refactoring-07-system-theme.md | 83 +++++++++++++++++ ...heme-refactoring-08-syntax-highlighting.md | 83 +++++++++++++++++ .../theme-refactoring-09-theme-utils.md | 77 +++++++++++++++ .../theme-refactoring-10-theme-switching.md | 80 ++++++++++++++++ .../theme-refactoring-11-custom-themes.md | 77 +++++++++++++++ 15 files changed, 890 insertions(+), 140 deletions(-) delete mode 100644 src/utils/color.ts create mode 100644 tasks/subtasks/theme-refactoring-01-create-schema.md create mode 100644 tasks/subtasks/theme-refactoring-02-convert-themes.md create mode 100644 tasks/subtasks/theme-refactoring-03-update-types.md create mode 100644 tasks/subtasks/theme-refactoring-04-theme-resolution.md create mode 100644 tasks/subtasks/theme-refactoring-05-theme-context.md create mode 100644 tasks/subtasks/theme-refactoring-06-theme-loader.md create mode 100644 tasks/subtasks/theme-refactoring-07-system-theme.md create mode 100644 tasks/subtasks/theme-refactoring-08-syntax-highlighting.md create mode 100644 tasks/subtasks/theme-refactoring-09-theme-utils.md create mode 100644 tasks/subtasks/theme-refactoring-10-theme-switching.md create mode 100644 tasks/subtasks/theme-refactoring-11-custom-themes.md diff --git a/src/components/PreferencesPanel.tsx b/src/components/PreferencesPanel.tsx index bff2914..509a2ea 100644 --- a/src/components/PreferencesPanel.tsx +++ b/src/components/PreferencesPanel.tsx @@ -1,7 +1,6 @@ import { createSignal } from "solid-js" import { useKeyboard } from "@opentui/solid" import { useAppStore } from "../stores/app" -import { createColorResolver } from "../utils/color" import type { ThemeName } from "../types/settings" type FocusField = "theme" | "font" | "speed" | "explicit" | "auto" @@ -22,8 +21,6 @@ export function PreferencesPanel() { const settings = () => appStore.state().settings const preferences = () => appStore.state().preferences - const resolveColor = createColorResolver(appStore.resolveTheme()) - const handleKey = (key: { name: string; shift?: boolean }) => { if (key.name === "tab") { const fields: FocusField[] = ["theme", "font", "speed", "explicit", "auto"] @@ -79,55 +76,55 @@ export function PreferencesPanel() { return ( - Preferences + Preferences - Theme: + Theme: - {THEME_LABELS.find((t) => t.value === settings().theme)?.label} + {THEME_LABELS.find((t) => t.value === settings().theme)?.label} - [Left/Right] + [Left/Right] - Font Size: + Font Size: - {settings().fontSize}px + {settings().fontSize}px - [Left/Right] + [Left/Right] - Playback: + Playback: - {settings().playbackSpeed}x + {settings().playbackSpeed}x - [Left/Right] + [Left/Right] - Show Explicit: + Show Explicit: - + {preferences().showExplicit ? "On" : "Off"} - [Space] + [Space] - Auto Download: + Auto Download: - + {preferences().autoDownload ? "On" : "Off"} - [Space] + [Space] - Tab to move focus, Left/Right to adjust + Tab to move focus, Left/Right to adjust ) } diff --git a/src/components/SourceManager.tsx b/src/components/SourceManager.tsx index 7b1831a..903c75a 100644 --- a/src/components/SourceManager.tsx +++ b/src/components/SourceManager.tsx @@ -6,7 +6,6 @@ import { createSignal, For } from "solid-js" import { useFeedStore } from "../stores/feed" import { SourceType } from "../types/source" -import { createColorResolver } from "../utils/color" import type { PodcastSource } from "../types/source" interface SourceManagerProps { @@ -149,8 +148,6 @@ export function SourceManager(props: SourceManagerProps) { const sourceExplicit = () => selectedSource()?.allowExplicit !== false const sourceLanguage = () => selectedSource()?.language || "en_us" - const resolveColor = createColorResolver({}) - return ( @@ -158,15 +155,15 @@ export function SourceManager(props: SourceManagerProps) { Podcast Sources - [Esc] Close + [Esc] Close - Manage where to search for podcasts + Manage where to search for podcasts {/* Source list */} - Sources: + Sources: {(source, index) => ( @@ -176,7 +173,7 @@ export function SourceManager(props: SourceManagerProps) { padding={0} backgroundColor={ focusArea() === "list" && index() === selectedIndex() - ? resolveColor("--color-primary") + ? "var(--color-primary)" : undefined } onMouseDown={() => { @@ -187,21 +184,21 @@ export function SourceManager(props: SourceManagerProps) { > {focusArea() === "list" && index() === selectedIndex() ? ">" : " "} - + {source.enabled ? "[x]" : "[ ]"} - {getSourceIcon(source)} + {getSourceIcon(source)} @@ -211,7 +208,7 @@ export function SourceManager(props: SourceManagerProps) { )} - Space/Enter to toggle, d to delete, a to add + Space/Enter to toggle, d to delete, a to add {/* API settings */} diff --git a/src/context/ThemeContext.tsx b/src/context/ThemeContext.tsx index 42b73e6..5b2484a 100644 --- a/src/context/ThemeContext.tsx +++ b/src/context/ThemeContext.tsx @@ -42,21 +42,18 @@ export function ThemeProvider({ children }: { children: any }) { // Handle system theme changes createEffect(() => { if (isSystemTheme()) { - // Check if window and matchMedia are available - if (typeof window !== "undefined" && typeof window.matchMedia === "function") { - const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)") - const handler = () => { - const newMode = getSystemThemeMode() - setCurrentMode(newMode) - setResolvedTheme(appStore.resolveTheme()) - } - - mediaQuery.addEventListener("change", handler) - - onCleanup(() => { - mediaQuery.removeEventListener("change", handler) - }) + const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)") + const handler = () => { + const newMode = getSystemThemeMode() + setCurrentMode(newMode) + setResolvedTheme(appStore.resolveTheme()) } + + mediaQuery.addEventListener("change", handler) + + onCleanup(() => { + mediaQuery.removeEventListener("change", handler) + }) } }) diff --git a/src/utils/color.ts b/src/utils/color.ts deleted file mode 100644 index 91e921c..0000000 --- a/src/utils/color.ts +++ /dev/null @@ -1,93 +0,0 @@ -/** - * Color Resolution Utility - * Converts CSS variable references to actual color values - */ - -/** - * Map of CSS variable names to their default color values - * Used as fallback when CSS variables aren't resolved - */ -const CSS_VARIABLE_MAP: Record = { - "--color-background": "transparent", - "--color-surface": "#1b1f27", - "--color-primary": "#6fa8ff", - "--color-secondary": "#a9b1d6", - "--color-accent": "#f6c177", - "--color-text": "#e6edf3", - "--color-muted": "#7d8590", - "--color-warning": "#f0b429", - "--color-error": "#f47067", - "--color-success": "#3fb950", - "--color-layer0": "transparent", - "--color-layer1": "#1e222e", - "--color-layer2": "#161b22", - "--color-layer3": "#0d1117", -} - -/** - * Resolves a CSS variable reference to an actual color value - * @param variable The CSS variable string (e.g., "var(--color-primary)") - * @returns The resolved color value or a default fallback - */ -export function resolveCSSVariable(variable: string): string { - if (!variable || typeof variable !== "string") { - return "#ff00ff" // Default magenta fallback - } - - // Extract the variable name from var(--name) - const match = variable.match(/var\(([^)]+)\)/) - if (match && match[1]) { - const varName = match[1].trim() - // Get the computed style value from the document - if (typeof document !== "undefined") { - const root = document.documentElement - const computedValue = getComputedStyle(root).getPropertyValue(varName) - if (computedValue) { - return computedValue.trim() - } - } - // Fall back to the map - return CSS_VARIABLE_MAP[varName] || "#ff00ff" - } - - // Return the original value if it's not a CSS variable - return variable -} - -/** - * Creates a function that resolves CSS variables from a theme object - * @param theme The theme object with color properties - * @returns A function that resolves CSS variable strings to actual colors - */ -export function createColorResolver(theme: { - background?: string - surface?: string - primary?: string - secondary?: string - accent?: string - text?: string - muted?: string - warning?: string - error?: string - success?: string - layerBackgrounds?: { - layer0?: string - layer1?: string - layer2?: string - layer3?: string - } -}) { - return (color: string | undefined): string => { - if (!color) { - return "#ff00ff" // Default magenta fallback - } - - // If it's already a valid hex or named color, return it - if (/^#([0-9A-Fa-f]{3}|[0-9A-Fa-f]{6})$/.test(color) || /^[a-z]+$/i.test(color)) { - return color - } - - // Otherwise, try to resolve it as a CSS variable - return resolveCSSVariable(color) - } -} diff --git a/tasks/subtasks/theme-refactoring-01-create-schema.md b/tasks/subtasks/theme-refactoring-01-create-schema.md new file mode 100644 index 0000000..1415d98 --- /dev/null +++ b/tasks/subtasks/theme-refactoring-01-create-schema.md @@ -0,0 +1,63 @@ +# 01. Create JSON Theme Schema and File Structure + +meta: + id: theme-refactoring-01 + feature: theme-refactoring-json-format + priority: P0 + depends_on: [] + tags: [implementation, infrastructure] + +objective: +- Create the JSON theme schema and establish the file structure for theme definitions +- Define the theme.json schema that opencode uses +- Create the directory structure for JSON theme files + +deliverables: +- `src/types/theme-schema.ts` - JSON theme schema definition +- `src/themes/*.json` - Directory for theme JSON files +- `src/themes/schema.json` - Theme schema reference + +steps: +- Step 1.1: Create `src/types/theme-schema.ts` with TypeScript interfaces matching the opencode theme JSON structure + - Define `ThemeJson` interface with `$schema`, `defs`, and `theme` properties + - Define `ColorValue` type supporting hex colors, color references, variants, and RGBA + - Define `Variant` type for light/dark mode color definitions + - Export interfaces for type checking + +- Step 1.2: Create `src/themes/schema.json` with the opencode theme schema reference + - Add `$schema: "https://opencode.ai/theme.json"` + - Document the theme structure in comments + +- Step 1.3: Create `src/themes/` directory + - Ensure directory exists for JSON theme files + +- Step 1.4: Create a sample theme file in `src/themes/opencode.json` + - Use the opencode theme as reference + - Include proper `$schema` reference + - Define `defs` with all color references + - Define `theme` with semantic color mappings + +tests: +- Unit: + - Test `ThemeJson` type definition matches opencode structure + - Test `ColorValue` type accepts hex colors, references, variants, and RGBA + - Test `Variant` type structure is correct + +- Integration/e2e: + - Verify JSON file can be parsed without errors + - Validate schema reference is correct + +acceptance_criteria: +- `src/types/theme-schema.ts` file exists with all required interfaces +- `src/themes/schema.json` contains valid schema reference +- `src/themes/` directory is created +- `src/themes/opencode.json` can be imported and parsed successfully + +validation: +- Run: `bun run typecheck` - Should pass with no type errors +- Run: `cat src/themes/opencode.json | jq .` - Should be valid JSON + +notes: +- Follow opencode's theme.json structure exactly +- Use TypeScript interfaces to ensure type safety +- Reference: `/home/mike/code/PodTui/opencode/packages/opencode/src/cli/cmd/tui/context/theme/` diff --git a/tasks/subtasks/theme-refactoring-02-convert-themes.md b/tasks/subtasks/theme-refactoring-02-convert-themes.md new file mode 100644 index 0000000..2091324 --- /dev/null +++ b/tasks/subtasks/theme-refactoring-02-convert-themes.md @@ -0,0 +1,77 @@ +# 02. Convert Existing Themes to JSON Format + +meta: + id: theme-refactoring-02 + feature: theme-refactoring-json-format + priority: P0 + depends_on: [theme-refactoring-01] + tags: [implementation, migration] + +objective: +- Convert all existing PodTui themes (catppuccin, gruvbox, tokyo, nord) from TypeScript constants to JSON format +- Ensure each theme matches the opencode JSON structure +- Maintain color fidelity with original theme definitions + +deliverables: +- `src/themes/catppuccin.json` - Catppuccin theme in JSON format +- `src/themes/gruvbox.json` - Gruvbox theme in JSON format +- `src/themes/tokyo.json` - Tokyo Night theme in JSON format +- `src/themes/nord.json` - Nord theme in JSON format + +steps: +- Step 2.1: Convert `catppuccin` theme from `src/types/desktop-theme.ts` to JSON + - Extract all color definitions from `THEMES_DESKTOP.variants.find((v) => v.name === "catppuccin")!.colors` + - Create `defs` object with all color references (dark and light variants) + - Create `theme` object with semantic mappings + - Add `$schema` reference + - Verify color values match original definitions + +- Step 2.2: Convert `gruvbox` theme from `src/types/desktop-theme.ts` to JSON + - Extract all color definitions from `THEMES_DESKTOP.variants.find((v) => v.name === "gruvbox")!.colors` + - Create `defs` object with all color references + - Create `theme` object with semantic mappings + - Add `$schema` reference + +- Step 2.3: Convert `tokyo` theme from `src/types/desktop-theme.ts` to JSON + - Extract all color definitions from `THEMES_DESKTOP.variants.find((v) => v.name === "tokyo")!.colors` + - Create `defs` object with all color references + - Create `theme` object with semantic mappings + - Add `$schema` reference + +- Step 2.4: Convert `nord` theme from `src/types/desktop-theme.ts` to JSON + - Extract all color definitions from `THEMES_DESKTOP.variants.find((v) => v.name === "nord")!.colors` + - Create `defs` object with all color references + - Create `theme` object with semantic mappings + - Add `$schema` reference + +- Step 2.5: Verify all JSON files are valid + - Check syntax with `bun run typecheck` + - Ensure all imports work correctly + +tests: +- Unit: + - Test each JSON file can be imported without errors + - Verify color values match original TypeScript definitions + +- Integration/e2e: + - Load each theme and verify all colors are present + - Check that theme structure matches expected schema + +acceptance_criteria: +- All four theme JSON files exist in `src/themes/` +- Each JSON file follows the theme schema +- Color values match original theme definitions exactly +- All JSON files are valid and can be parsed + +validation: +- Run: `bun run typecheck` - Should pass +- Run: `cat src/themes/catppuccin.json | jq .` - Should be valid JSON +- Run: `cat src/themes/gruvbox.json | jq .` - Should be valid JSON +- Run: `cat src/themes/tokyo.json | jq .` - Should be valid JSON +- Run: `cat src/themes/nord.json | jq .` - Should be valid JSON + +notes: +- Use opencode's theme structure as reference +- Maintain backward compatibility with existing color definitions +- Ensure both dark and light variants are included if available +- Reference: `/home/mike/code/PodTui/opencode/packages/opencode/src/cli/cmd/tui/context/theme/` diff --git a/tasks/subtasks/theme-refactoring-03-update-types.md b/tasks/subtasks/theme-refactoring-03-update-types.md new file mode 100644 index 0000000..1a8b944 --- /dev/null +++ b/tasks/subtasks/theme-refactoring-03-update-types.md @@ -0,0 +1,70 @@ +# 03. Update Type Definitions for Color References and Variants + +meta: + id: theme-refactoring-03 + feature: theme-refactoring-json-format + priority: P0 + depends_on: [theme-refactoring-01] + tags: [implementation, types] + +objective: +- Update type definitions to support the new JSON theme structure +- Add support for color references, variants, and light/dark mode +- Maintain backward compatibility with existing code + +deliverables: +- `src/types/theme-schema.ts` - Updated with new types +- `src/types/settings.ts` - Updated with color reference types +- `src/types/desktop-theme.ts` - Updated to support JSON themes + +steps: +- Step 3.1: Update `src/types/theme-schema.ts` + - Export `ThemeJson` interface + - Export `ColorValue` type + - Export `Variant` type + - Add `ThemeColors` type for resolved theme colors + +- Step 3.2: Update `src/types/settings.ts` + - Add `ThemeJson` import + - Add `ColorValue` type definition + - Add `Variant` type definition + - Update `ThemeColors` to support color references + - Add `ThemeJson` type for JSON theme files + +- Step 3.3: Update `src/types/desktop-theme.ts` + - Add imports for `ThemeJson`, `ColorValue`, `Variant` + - Add `ThemeJson` type for JSON theme files + - Update existing types to support color references + - Add helper functions for JSON theme loading + +- Step 3.4: Ensure backward compatibility + - Keep existing `ThemeColors` structure for resolved themes + - Ensure existing code can still use theme colors as strings + - Add type guards for color references + +tests: +- Unit: + - Test `ThemeJson` type accepts valid JSON theme structure + - Test `ColorValue` type accepts hex colors, references, variants, and RGBA + - Test `Variant` type structure is correct + - Test existing `ThemeColors` type remains compatible + +- Integration/e2e: + - Verify type imports work correctly + - Test type inference with JSON theme files + +acceptance_criteria: +- All type definitions are updated and exported +- Backward compatibility maintained with existing code +- New types support color references and variants +- Type checking passes without errors + +validation: +- Run: `bun run typecheck` - Should pass with no errors +- Verify existing components can still use theme colors +- Test type inference with new theme JSON files + +notes: +- Use TypeScript's `with { type: "json" }` for JSON imports +- Ensure all types are properly exported for use across the codebase +- Reference: `/home/mike/code/PodTui/opencode/packages/opencode/src/cli/cmd/tui/context/theme.tsx` diff --git a/tasks/subtasks/theme-refactoring-04-theme-resolution.md b/tasks/subtasks/theme-refactoring-04-theme-resolution.md new file mode 100644 index 0000000..e0afc8a --- /dev/null +++ b/tasks/subtasks/theme-refactoring-04-theme-resolution.md @@ -0,0 +1,83 @@ +# 04. Create Theme Resolution Logic with Color Reference Lookup + +meta: + id: theme-refactoring-04 + feature: theme-refactoring-json-format + priority: P0 + depends_on: [theme-refactoring-02, theme-refactoring-03] + tags: [implementation, logic] + +objective: +- Implement theme resolution logic that handles color references and variants +- Create function to resolve colors from theme JSON files +- Support hex colors, color references, ANSI codes, and RGBA values +- Handle light/dark mode selection based on current mode + +deliverables: +- `src/utils/theme-resolver.ts` - Theme resolution utility +- `src/utils/ansi-to-rgba.ts` - ANSI color conversion utility + +steps: +- Step 4.1: Create `src/utils/ansi-to-rgba.ts` + - Implement `ansiToRgba(code: number): RGBA` function + - Handle standard ANSI colors (0-15) + - Handle 6x6x6 color cube (16-231) + - Handle grayscale ramp (232-255) + - Add type definitions for RGBA + +- Step 4.2: Create `src/utils/theme-resolver.ts` + - Implement `resolveTheme(theme: ThemeJson, mode: "dark" | "light"): ThemeColors` + - Create `resolveColor(c: ColorValue): RGBA` helper function + - Handle RGBA objects directly + - Handle hex color strings + - Handle color references from `defs` + - Handle variants (dark/light mode) + - Handle ANSI codes + - Add error handling for invalid color references + +- Step 4.3: Implement color reference resolution + - Create lookup logic for `defs` object + - Add fallback to theme colors if reference not in defs + - Throw descriptive errors for invalid references + +- Step 4.4: Handle optional theme properties + - Support `selectedListItemText` property + - Support `backgroundMenu` property + - Support `thinkingOpacity` property + - Add default values for missing properties + +tests: +- Unit: + - Test `ansiToRgba` with ANSI codes 0-15 + - Test `ansiToRgba` with color cube codes 16-231 + - Test `ansiToRgba` with grayscale codes 232-255 + - Test `resolveColor` with hex colors + - Test `resolveColor` with color references + - Test `resolveColor` with light/dark variants + - Test `resolveColor` with RGBA objects + - Test `resolveTheme` with complete theme JSON + - Test `resolveTheme` with missing optional properties + - Test error handling for invalid color references + +- Integration/e2e: + - Test resolving colors from actual theme JSON files + - Verify light/dark mode selection works correctly + +acceptance_criteria: +- `src/utils/ansi-to-rgba.ts` file exists with conversion functions +- `src/utils/theme-resolver.ts` file exists with resolution logic +- All color value types are handled correctly +- Error messages are descriptive and helpful +- Theme resolution works with both light and dark modes + +validation: +- Run: `bun run typecheck` - Should pass +- Run unit tests with `bun test src/utils/theme-resolver.test.ts` +- Test with sample theme JSON files +- Verify error messages are clear + +notes: +- Use opencode's implementation as reference for color resolution +- Ensure RGBA values are normalized to 0-1 range +- Add comprehensive error handling for invalid inputs +- Reference: `/home/mike/code/PodTui/opencode/packages/opencode/src/cli/cmd/tui/context/theme.tsx` (lines 176-277) diff --git a/tasks/subtasks/theme-refactoring-05-theme-context.md b/tasks/subtasks/theme-refactoring-05-theme-context.md new file mode 100644 index 0000000..50199ad --- /dev/null +++ b/tasks/subtasks/theme-refactoring-05-theme-context.md @@ -0,0 +1,80 @@ +# 05. Migrate ThemeContext to SolidJS Pattern + +meta: + id: theme-refactoring-05 + feature: theme-refactoring-json-format + priority: P0 + depends_on: [theme-refactoring-04] + tags: [implementation, context] + +objective: +- Migrate ThemeContext from basic React context to SolidJS context pattern +- Implement reactive state management for theme switching +- Add persistence for theme selection and mode +- Support system theme detection + +deliverables: +- `src/context/ThemeContext.tsx` - Updated with SolidJS pattern +- `src/utils/theme-context.ts` - Theme context utilities + +steps: +- Step 5.1: Update `src/context/ThemeContext.tsx` + - Import SolidJS hooks: `createSignal`, `createEffect`, `createMemo`, `createStore` + - Replace React context with SolidJS `createSimpleContext` pattern (from opencode) + - Add theme loading logic + - Implement reactive theme state + - Add system theme detection + - Support theme persistence via localStorage + +- Step 5.2: Implement theme state management + - Create store with `themes`, `mode`, `active`, `ready` + - Initialize with default theme (opencode) + - Load custom themes from JSON files + - Handle system theme detection + +- Step 5.3: Add reactive theme resolution + - Create `createMemo` for resolved theme colors + - Create `createMemo` for syntax highlighting + - Create `createMemo` for subtle syntax + +- Step 5.4: Implement theme switching + - Add `setTheme(theme: string)` method + - Add `setMode(mode: "dark" | "light")` method + - Persist theme and mode to localStorage + +- Step 5.5: Add system theme detection + - Detect terminal background and foreground colors + - Generate system theme based on terminal palette + - Handle system theme preference changes + +tests: +- Unit: + - Test theme state initialization + - Test theme switching logic + - Test mode switching logic + - Test system theme detection + - Test localStorage persistence + +- Integration/e2e: + - Test theme context in component tree + - Test reactive theme updates + - Test system theme changes + +acceptance_criteria: +- `src/context/ThemeContext.tsx` uses SolidJS pattern +- Theme context provides reactive theme state +- Theme switching works correctly +- System theme detection is functional +- Theme and mode are persisted to localStorage + +validation: +- Run: `bun run typecheck` - Should pass +- Run: `bun test src/context/ThemeContext.test.ts` +- Test theme switching in application +- Test system theme detection + +notes: +- Use opencode's ThemeProvider pattern as reference +- Follow SolidJS best practices for reactive state +- Ensure proper cleanup of effects and listeners +- Reference: `/home/mike/code/PodTui/opencode/packages/opencode/src/cli/cmd/tui/context/theme.tsx` (lines 279-392) diff --git a/tasks/subtasks/theme-refactoring-06-theme-loader.md b/tasks/subtasks/theme-refactoring-06-theme-loader.md new file mode 100644 index 0000000..94185fa --- /dev/null +++ b/tasks/subtasks/theme-refactoring-06-theme-loader.md @@ -0,0 +1,79 @@ +# 06. Add Theme Loader for JSON Files and Custom Themes + +meta: + id: theme-refactoring-06 + feature: theme-refactoring-json-format + priority: P1 + depends_on: [theme-refactoring-02, theme-refactoring-04] + tags: [implementation, loading] + +objective: +- Create theme loader to load JSON theme files +- Support loading custom themes from multiple directories +- Provide API for theme discovery and loading +- Handle theme file validation + +deliverables: +- `src/utils/theme-loader.ts` - Theme loader utilities +- `src/utils/custom-themes.ts` - Custom theme loading logic + +steps: +- Step 6.1: Create `src/utils/theme-loader.ts` + - Implement `loadTheme(name: string): Promise` + - Implement `loadThemeFromPath(path: string): Promise` + - Implement `getAllThemes(): Promise>` + - Add error handling for missing or invalid theme files + +- Step 6.2: Create `src/utils/custom-themes.ts` + - Implement `getCustomThemes()` function + - Scan for theme files in multiple directories: + - `~/.config/podtui/themes/` + - `./.podtui/themes/` + - Project root `./themes/` + - Support custom theme files with `.json` extension + - Return merged theme registry + +- Step 6.3: Add theme file validation + - Validate theme JSON structure + - Check required properties (`defs`, `theme`) + - Validate color references in `defs` + - Add warning for optional properties + +- Step 6.4: Implement theme discovery + - List all available theme files + - Provide theme metadata (name, description) + - Support theme aliases (e.g., "catppuccin" -> "catppuccin.json") + +tests: +- Unit: + - Test `loadTheme` with existing theme files + - Test `loadTheme` with missing theme files + - Test `loadThemeFromPath` with custom paths + - Test `getAllThemes` returns all available themes + - Test `getCustomThemes` scans multiple directories + - Test theme file validation + +- Integration/e2e: + - Test loading all available themes + - Test custom theme loading from directories + - Verify theme discovery works correctly + +acceptance_criteria: +- `src/utils/theme-loader.ts` file exists with loading functions +- `src/utils/custom-themes.ts` file exists with custom theme logic +- Custom themes can be loaded from multiple directories +- Theme validation prevents invalid files +- Theme discovery API is functional + +validation: +- Run: `bun run typecheck` - Should pass +- Run: `bun test src/utils/theme-loader.test.ts` +- Run: `bun test src/utils/custom-themes.test.ts` +- Test loading all available themes manually +- Test custom theme loading from directories + +notes: +- Use opencode's `getCustomThemes` pattern as reference +- Support both local and global theme directories +- Add comprehensive error messages for invalid theme files +- Reference: `/home/mike/code/PodTui/opencode/packages/opencode/src/cli/cmd/tui/context/theme.tsx` (lines 394-419) diff --git a/tasks/subtasks/theme-refactoring-07-system-theme.md b/tasks/subtasks/theme-refactoring-07-system-theme.md new file mode 100644 index 0000000..25a7912 --- /dev/null +++ b/tasks/subtasks/theme-refactoring-07-system-theme.md @@ -0,0 +1,83 @@ +# 07. Implement System Theme Detection with Terminal Palette + +meta: + id: theme-refactoring-07 + feature: theme-refactoring-json-format + priority: P1 + depends_on: [theme-refactoring-04, theme-refactoring-06] + tags: [implementation, detection] + +objective: +- Implement system theme detection based on terminal palette +- Generate system theme from terminal colors +- Detect light/dark mode based on terminal background +- Handle terminal color palette limitations + +deliverables: +- `src/utils/system-theme.ts` - System theme detection utilities +- `src/utils/color-generation.ts` - Color generation helpers + +steps: +- Step 7.1: Create `src/utils/system-theme.ts` + - Implement `detectSystemTheme()` function + - Detect terminal background and foreground colors + - Determine light/dark mode based on luminance + - Return detected theme information + +- Step 7.2: Implement terminal palette detection + - Detect terminal colors using `@opentui/core` renderer + - Get default background and foreground colors + - Extract color palette (16 standard colors) + - Handle missing or invalid palette data + +- Step 7.3: Create `src/utils/color-generation.ts` + - Implement `generateGrayScale(bg: RGBA, isDark: boolean): Record` + - Implement `generateMutedTextColor(bg: RGBA, isDark: boolean): RGBA` + - Implement `tint(base: RGBA, overlay: RGBA, alpha: number): RGBA` + - Generate gray scale based on background luminance + - Generate muted text colors for readability + +- Step 7.4: Create system theme JSON generator + - Implement `generateSystemTheme(colors: TerminalColors, mode: "dark" | "light"): ThemeJson` + - Use ANSI color references for primary colors + - Generate appropriate background colors + - Generate diff colors with alpha blending + - Generate markdown and syntax colors + +- Step 7.5: Add system theme caching + - Cache terminal palette detection results + - Handle palette cache invalidation + - Support manual cache clear on SIGUSR2 + +tests: +- Unit: + - Test `detectSystemTheme` returns correct mode + - Test `generateGrayScale` produces correct grays + - Test `generateMutedTextColor` produces readable colors + - Test `tint` produces correct blended colors + - Test `generateSystemTheme` produces valid theme JSON + +- Integration/e2e: + - Test system theme detection in terminal + - Test theme generation with actual terminal palette + - Verify light/dark mode detection is accurate + +acceptance_criteria: +- `src/utils/system-theme.ts` file exists with detection functions +- `src/utils/color-generation.ts` file exists with generation helpers +- System theme detection works correctly +- Light/dark mode detection is accurate +- Theme generation produces valid JSON + +validation: +- Run: `bun run typecheck` - Should pass +- Run: `bun test src/utils/system-theme.test.ts` +- Run: `bun test src/utils/color-generation.test.ts` +- Test system theme detection manually in terminal +- Verify theme colors are readable + +notes: +- Use opencode's system theme detection as reference +- Handle terminal transparency gracefully +- Add fallback for terminals without palette support +- Reference: `/home/mike/code/PodTui/opencode/packages/opencode/src/cli/cmd/tui/context/theme.tsx` (lines 428-535) diff --git a/tasks/subtasks/theme-refactoring-08-syntax-highlighting.md b/tasks/subtasks/theme-refactoring-08-syntax-highlighting.md new file mode 100644 index 0000000..01ec116 --- /dev/null +++ b/tasks/subtasks/theme-refactoring-08-syntax-highlighting.md @@ -0,0 +1,83 @@ +# 08. Add Syntax Highlighting Integration + +meta: + id: theme-refactoring-08 + feature: theme-refactoring-json-format + priority: P1 + depends_on: [theme-refactoring-04, theme-refactoring-05] + tags: [implementation, syntax] + +objective: +- Add syntax highlighting support using theme colors +- Generate syntax rules from theme definitions +- Support markdown syntax highlighting +- Integrate with OpenTUI syntax highlighting + +deliverables: +- `src/utils/syntax-highlighter.ts` - Syntax highlighting utilities +- `src/utils/syntax-rules.ts` - Syntax rule generation + +steps: +- Step 8.1: Create `src/utils/syntax-rules.ts` + - Implement `getSyntaxRules(theme: ThemeColors)` function + - Define syntax scopes and their mappings + - Map theme colors to syntax scopes: + - Default text + - Keywords (return, conditional, repeat, coroutine) + - Types (function, class, module) + - Variables (parameter, member, builtin) + - Strings, numbers, booleans + - Comments + - Operators and punctuation + - Markdown-specific scopes (headings, bold, italic, links) + - Diff scopes (added, removed, context) + - Add style properties (foreground, bold, italic, underline) + +- Step 8.2: Create `src/utils/syntax-highlighter.ts` + - Implement `generateSyntax(theme: ThemeColors)` function + - Implement `generateSubtleSyntax(theme: ThemeColors)` function + - Apply opacity to syntax colors for subtle highlighting + - Use theme's `thinkingOpacity` property + +- Step 8.3: Integrate with OpenTUI syntax highlighting + - Import `SyntaxStyle` from `@opentui/core` + - Use `SyntaxStyle.fromTheme()` to create syntax styles + - Apply syntax styles to code components + +- Step 8.4: Add syntax scope mappings + - Map common programming language scopes + - Map markdown and markup scopes + - Map diff and git scopes + - Add scope aliases for common patterns + +tests: +- Unit: + - Test `getSyntaxRules` generates correct rules + - Test `generateSyntax` creates valid syntax styles + - Test `generateSubtleSyntax` applies opacity correctly + - Test syntax rules cover all expected scopes + +- Integration/e2e: + - Test syntax highlighting with different themes + - Verify syntax colors match theme definitions + - Test markdown highlighting + +acceptance_criteria: +- `src/utils/syntax-rules.ts` file exists with rule generation +- `src/utils/syntax-highlighter.ts` file exists with style generation +- Syntax highlighting works with theme colors +- Markdown highlighting is supported +- Syntax rules cover common programming patterns + +validation: +- Run: `bun run typecheck` - Should pass +- Run: `bun test src/utils/syntax-rules.test.ts` +- Run: `bun test src/utils/syntax-highlighter.test.ts` +- Test syntax highlighting in application +- Verify syntax colors are readable + +notes: +- Use opencode's syntax rule generation as reference +- Include comprehensive scope mappings +- Support common programming languages +- Reference: `/home/mike/code/PodTui/opencode/packages/opencode/src/cli/cmd/tui/context/theme.tsx` (lines 622-1152) diff --git a/tasks/subtasks/theme-refactoring-09-theme-utils.md b/tasks/subtasks/theme-refactoring-09-theme-utils.md new file mode 100644 index 0000000..affde61 --- /dev/null +++ b/tasks/subtasks/theme-refactoring-09-theme-utils.md @@ -0,0 +1,77 @@ +# 09. Update Theme Utilities and CSS Variable Application + +meta: + id: theme-refactoring-09 + feature: theme-refactoring-json-format + priority: P1 + depends_on: [theme-refactoring-04] + tags: [implementation, utilities] + +objective: +- Update existing theme utilities to work with JSON theme structure +- Refactor CSS variable application logic +- Add support for theme color references +- Ensure backward compatibility with existing components + +deliverables: +- `src/utils/theme.ts` - Updated theme utilities +- `src/utils/theme-css.ts` - CSS variable application utilities + +steps: +- Step 9.1: Update `src/utils/theme.ts` + - Refactor `applyTheme()` to accept `ThemeColors` type + - Keep existing function signature for backward compatibility + - Update to work with resolved theme colors + +- Step 9.2: Create `src/utils/theme-css.ts` + - Implement `applyThemeToCSS(theme: ThemeColors)` function + - Apply theme colors as CSS custom properties + - Support all theme color properties + - Handle layer backgrounds if present + +- Step 9.3: Update theme attribute handling + - Implement `setThemeAttribute(themeName: string)` function + - Update to use data-theme attribute + - Support system theme attribute + +- Step 9.4: Add color reference support + - Implement `resolveColorReference(color: string): string` function + - Convert color references to CSS values + - Handle hex colors, color references, and RGBA + +- Step 9.5: Add theme utility functions + - Implement `getThemeByName(name: string): ThemeJson | undefined` + - Implement `getDefaultTheme(): ThemeJson` + - Implement `getAllThemes(): ThemeJson[]` + +tests: +- Unit: + - Test `applyThemeToCSS` applies all colors correctly + - Test `setThemeAttribute` sets attribute correctly + - Test `resolveColorReference` converts references correctly + - Test theme utility functions return correct results + +- Integration/e2e: + - Test theme application in browser + - Verify CSS variables are updated correctly + - Test theme attribute changes + +acceptance_criteria: +- `src/utils/theme.ts` is updated and backward compatible +- `src/utils/theme-css.ts` file exists with CSS utilities +- CSS variables are applied correctly +- Color references are resolved properly +- Theme utilities are functional + +validation: +- Run: `bun run typecheck` - Should pass +- Run: `bun test src/utils/theme.test.ts` +- Run: `bun test src/utils/theme-css.test.ts` +- Test theme application in browser +- Verify CSS variables are applied correctly + +notes: +- Maintain backward compatibility with existing code +- Use CSS custom properties for theming +- Ensure all theme colors are applied +- Reference: `/home/mike/code/PodTui/src/utils/theme.ts` (original file) diff --git a/tasks/subtasks/theme-refactoring-10-theme-switching.md b/tasks/subtasks/theme-refactoring-10-theme-switching.md new file mode 100644 index 0000000..3135e38 --- /dev/null +++ b/tasks/subtasks/theme-refactoring-10-theme-switching.md @@ -0,0 +1,80 @@ +# 10. Test Theme Switching and Light/Dark Mode + +meta: + id: theme-refactoring-10 + feature: theme-refactoring-json-format + priority: P0 + depends_on: [theme-refactoring-05, theme-refactoring-09] + tags: [testing, verification] + +objective: +- Comprehensive testing of theme switching functionality +- Verify light/dark mode switching works correctly +- Test all theme JSON files load and apply correctly +- Ensure theme persistence works across sessions + +deliverables: +- `src/utils/theme.test.ts` - Theme utility tests +- `src/context/ThemeContext.test.ts` - Context tests +- Test results showing all themes work correctly + +steps: +- Step 10.1: Create `src/utils/theme.test.ts` + - Test theme loading functions + - Test theme resolution logic + - Test color reference resolution + - Test ANSI color conversion + +- Step 10.2: Create `src/context/ThemeContext.test.ts` + - Test theme context initialization + - Test theme switching + - Test mode switching + - Test system theme detection + - Test localStorage persistence + - Test reactive theme updates + +- Step 10.3: Manual testing + - Test switching between all themes (catppuccin, gruvbox, tokyo, nord) + - Test light/dark mode switching + - Test system theme detection + - Test theme persistence (close and reopen app) + - Test custom theme loading + +- Step 10.4: Visual verification + - Verify all theme colors are correct + - Check readability of text colors + - Verify background colors are appropriate + - Check that all UI elements use theme colors + +tests: +- Unit: + - Run all theme utility tests + - Run all theme context tests + - Verify all tests pass + +- Integration/e2e: + - Test theme switching in application + - Test light/dark mode switching + - Test theme persistence + - Test system theme detection + +acceptance_criteria: +- All unit tests pass +- All integration tests pass +- Theme switching works correctly +- Light/dark mode switching works correctly +- All themes load and apply correctly +- Theme persistence works across sessions + +validation: +- Run: `bun test src/utils/theme.test.ts` +- Run: `bun test src/context/ThemeContext.test.ts` +- Run: `bun test` - Run all tests +- Manual testing of all themes +- Visual verification of theme appearance + +notes: +- Test with actual terminal to verify system theme detection +- Verify all theme colors are visually appealing +- Check for any color contrast issues +- Test edge cases (missing themes, invalid colors) diff --git a/tasks/subtasks/theme-refactoring-11-custom-themes.md b/tasks/subtasks/theme-refactoring-11-custom-themes.md new file mode 100644 index 0000000..f7e6825 --- /dev/null +++ b/tasks/subtasks/theme-refactoring-11-custom-themes.md @@ -0,0 +1,77 @@ +# 11. Verify Custom Theme Loading and Persistence + +meta: + id: theme-refactoring-11 + feature: theme-refactoring-json-format + priority: P1 + depends_on: [theme-refactoring-06, theme-refactoring-10] + tags: [testing, verification] + +objective: +- Test custom theme loading from directories +- Verify theme persistence works correctly +- Test custom theme switching +- Ensure custom themes are loaded on app start + +deliverables: +- Test results for custom theme loading +- Documentation for custom theme format +- Verification that custom themes work correctly + +steps: +- Step 11.1: Create test theme files + - Create test theme in `~/.config/podtui/themes/` + - Create test theme in `./.podtui/themes/` + - Create test theme in `./themes/` + +- Step 11.2: Test custom theme loading + - Start application and verify custom themes are loaded + - Switch to custom theme + - Verify custom theme applies correctly + +- Step 11.3: Test theme persistence + - Set custom theme + - Close application + - Reopen application + - Verify custom theme is still selected + +- Step 11.4: Test theme discovery + - List all available themes + - Verify custom themes appear in list + - Test switching to custom themes + +- Step 11.5: Test invalid theme handling + - Create invalid theme JSON + - Verify error is handled gracefully + - Verify app doesn't crash + +tests: +- Unit: + - Test custom theme loading functions + - Test theme discovery + - Test invalid theme handling + +- Integration/e2e: + - Test custom theme loading from directories + - Test theme persistence + - Test theme discovery + - Test invalid theme handling + +acceptance_criteria: +- Custom themes can be loaded from directories +- Custom themes persist across sessions +- Custom themes appear in theme list +- Invalid themes are handled gracefully +- Theme discovery works correctly + +validation: +- Run: `bun test src/utils/custom-themes.test.ts` +- Run: `bun test` - Run all tests +- Manual testing of custom themes +- Verify themes persist after restart + +notes: +- Create documentation for custom theme format +- Reference: `/home/mike/code/PodTui/opencode/packages/opencode/src/cli/cmd/tui/context/theme.tsx` (lines 394-419) +- Test with multiple custom themes +- Verify all custom themes work correctly