Skip to content

Add UI toggle for dark/light theme #35

@alexh

Description

@alexh

Summary

Theme config exists but no runtime toggle. Add keybind or menu option to switch themes.

Key Features

  • Keybind to toggle theme (T key)
  • Theme persists in user config
  • Both themes have good contrast
  • Immediate visual update (no restart required)

Implementation Phases

Phase 1: Theme Architecture

  • Create src/ui/themes/ directory:
    themes/
      dark.ts    # Current cyberpunk/neon colors
      light.ts   # Light mode palette
      index.ts   # Theme loader
    
  • Theme interface:
    interface Theme {
      name: 'dark' | 'light';
      colors: {
        bg: string;
        fg: string;
        accent: string;
        header: { bg: string; fg: string };
        sidebar: { bg: string; selected: string };
        detail: { bg: string; border: string };
        status: Record<LoopStatus, string>;
        chart: { bar: string; axis: string };
      }
    }

Phase 2: Color Migration

  • Move hardcoded colors from src/config.ts to theme files
  • Current dark theme: magenta/cyan/green neon palette
  • Design light theme: neutral grays, blue accents, high contrast

Phase 3: Theme Loader

  • src/ui/themes/index.ts:
    let currentTheme: Theme;
    
    function loadTheme(name: 'dark' | 'light'): Theme;
    function getTheme(): Theme;
    function toggleTheme(): void;
  • Read initial theme from UserConfig.theme
  • Cache loaded theme in memory

Phase 4: UI Refresh

  • Add refreshTheme() function to src/ui/layout.ts
  • Update all widget styles from current theme
  • Call screen.render() after style updates

Phase 5: Keybind

  • Add T keybind in src/ui/screen.ts
  • On press: toggle theme, persist to config, refresh UI
  • Show brief toast: "Theme: Dark" / "Theme: Light"

Phase 6: Persistence

  • Update ~/.alex/config.yaml on toggle
  • Read on startup to restore preference

Theme Palettes

Dark Theme (current)

{
  bg: '#1a1a2e',
  fg: '#e0e0e0',
  accent: '#00ff88',
  header: { bg: '#16213e', fg: '#00ff88' },
  sidebar: { bg: '#0f0f23', selected: '#00ff88' },
  status: { running: '#00ffff', paused: '#ffff00', completed: '#00ff88', error: '#ff3366' }
}

Light Theme (proposed)

{
  bg: '#fafafa',
  fg: '#1a1a1a',
  accent: '#0066cc',
  header: { bg: '#e8e8e8', fg: '#0066cc' },
  sidebar: { bg: '#f0f0f0', selected: '#0066cc' },
  status: { running: '#0088cc', paused: '#cc8800', completed: '#00aa44', error: '#cc2244' }
}

Files to Create/Modify

  • src/ui/themes/dark.ts - Dark theme colors
  • src/ui/themes/light.ts - Light theme colors
  • src/ui/themes/index.ts - Theme loader
  • src/config.ts - Remove hardcoded colors, use theme getter
  • src/ui/layout.ts - Add refreshTheme() function
  • src/ui/screen.ts - Add T keybind
  • src/ui/theme.ts - Update to use theme loader

Acceptance Criteria

  • Keybind (T?) toggles theme
  • Theme persists in config
  • Both themes have good contrast
  • Immediate visual update (no restart)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions