Skip to content

feat(tui): implement live theme preview system#125

Merged
echobt merged 1 commit intomainfrom
feat/live-theme-preview
Feb 5, 2026
Merged

feat(tui): implement live theme preview system#125
echobt merged 1 commit intomainfrom
feat/live-theme-preview

Conversation

@echobt
Copy link
Contributor

@echobt echobt commented Feb 5, 2026

Summary

Adds a live theme preview system to the TUI, allowing users to preview theme colors in real-time before confirming their selection.

Changes

  • Add preview_theme field to AppState for temporary theme previews
  • Add methods: set_preview_theme, get_effective_theme_colors, start_theme_preview, cancel_theme_preview, confirm_theme_preview
  • Add ModalResult::ActionContinue variant for live preview without closing modal
  • Add ModalAction variants: PreviewTheme, RevertTheme, ConfirmTheme
  • Update ThemeSelectorModal to emit preview actions on navigation (Up/Down keys)
  • Add color swatch display in theme selector rows
  • Handle new theme actions in event loop
  • Update ThemePicker to use ThemeSelectorModal instead of interactive builder

How it works

  1. User opens theme selector via /themes command
  2. As user navigates through themes with arrow keys, the TUI immediately updates to show the selected theme's colors
  3. Pressing Escape reverts to the original theme
  4. Pressing Enter confirms and persists the new theme

Testing

  • Added comprehensive unit tests for preview functionality
  • Tested navigation behavior (Up/Down/Escape/Enter)
  • Verified color swatch rendering in theme rows

@greptile-apps
Copy link

greptile-apps bot commented Feb 5, 2026

Greptile Overview

Greptile Summary

This PR successfully implements a live theme preview system for the TUI, allowing users to see theme changes in real-time before committing to them.

Key Changes

  • Live Preview Architecture: Introduces preview_theme: Option<String> in AppState to track preview state separate from the active theme
  • New Modal Result Type: Adds ModalResult::ActionContinue to allow modals to emit actions while staying open (critical for live preview)
  • Theme Actions: Three new ModalAction variants handle the preview lifecycle:
    • PreviewTheme - Updates cached colors temporarily
    • ConfirmTheme - Persists the preview as the active theme
    • RevertTheme - Restores original theme on cancel
  • Enhanced UI: Theme list now displays color swatches showing each theme's primary color
  • Comprehensive Testing: All tests updated to verify preview behavior, with new tests for edge cases

Implementation Quality

The implementation is clean and well-structured:

  • Clear separation between preview and active theme state
  • Proper state management with lifecycle methods
  • Maintains backward compatibility with legacy theme selection
  • Excellent test coverage including boundary conditions
  • Documentation is thorough with clear explanations

The code follows existing patterns in the codebase and integrates seamlessly with the modal stack system.

Confidence Score: 5/5

  • This PR is safe to merge with high confidence - well-tested, clean implementation with no breaking changes
  • The implementation demonstrates excellent software engineering practices: comprehensive test coverage, clear state management, proper separation of concerns, and maintains backward compatibility. All changed files show high-quality code with no logical errors or security concerns.
  • No files require special attention

Important Files Changed

Filename Overview
src/cortex-tui/src/app/state.rs Added preview_theme field and helper methods for theme preview state management - clean implementation
src/cortex-tui/src/modal/mod.rs Added ActionContinue variant and new theme action types to enable live preview without closing modal
src/cortex-tui/src/modal/theme.rs Implemented live preview with color swatches, updated tests to verify preview behavior - comprehensive implementation
src/cortex-tui/src/runner/event_loop/modal.rs Implemented handlers for PreviewTheme, RevertTheme, and ConfirmTheme actions with proper state management

Sequence Diagram

sequenceDiagram
    participant User
    participant ThemeSelectorModal
    participant ModalStack
    participant EventLoop
    participant AppState
    participant ThemeColors

    User->>ThemeSelectorModal: Open /themes
    Note over ThemeSelectorModal: Stores original_theme<br/>for potential revert
    
    User->>ThemeSelectorModal: Press Down Arrow
    ThemeSelectorModal->>ThemeSelectorModal: navigate_down()
    ThemeSelectorModal->>ModalStack: ModalResult::ActionContinue(<br/>PreviewTheme("light"))
    ModalStack->>EventLoop: process_modal_action(<br/>PreviewTheme("light"))
    EventLoop->>AppState: start_theme_preview("light")
    AppState->>AppState: set_preview_theme(Some("light"))
    AppState->>ThemeColors: ThemeColors::from_name("light")
    ThemeColors-->>AppState: Updated colors
    Note over AppState: preview_theme = Some("light")<br/>theme_colors updated
    AppState-->>User: TUI updates with<br/>light theme colors

    User->>ThemeSelectorModal: Press Up Arrow
    ThemeSelectorModal->>ThemeSelectorModal: navigate_up()
    ThemeSelectorModal->>ModalStack: ModalResult::ActionContinue(<br/>PreviewTheme("dark"))
    ModalStack->>EventLoop: process_modal_action(<br/>PreviewTheme("dark"))
    EventLoop->>AppState: start_theme_preview("dark")
    AppState->>ThemeColors: ThemeColors::from_name("dark")
    ThemeColors-->>AppState: Updated colors
    AppState-->>User: TUI updates with<br/>dark theme colors

    alt User confirms selection
        User->>ThemeSelectorModal: Press Enter
        ThemeSelectorModal->>ModalStack: ModalResult::Action(<br/>ConfirmTheme("dark"))
        ModalStack->>ModalStack: pop() - closes modal
        ModalStack->>EventLoop: process_modal_action(<br/>ConfirmTheme("dark"))
        EventLoop->>AppState: set_theme("dark")
        Note over AppState: active_theme = "dark"<br/>preview_theme = None
        EventLoop->>EventLoop: Persist to config
        EventLoop-->>User: Toast: "Theme changed to: dark"
    else User cancels
        User->>ThemeSelectorModal: Press Esc
        ThemeSelectorModal->>ModalStack: ModalResult::Action(<br/>RevertTheme)
        ModalStack->>ModalStack: pop() - closes modal
        ModalStack->>EventLoop: process_modal_action(<br/>RevertTheme)
        EventLoop->>AppState: cancel_theme_preview()
        AppState->>AppState: set_preview_theme(None)
        AppState->>ThemeColors: ThemeColors::from_name(<br/>original active_theme)
        ThemeColors-->>AppState: Restored colors
        Note over AppState: preview_theme = None<br/>Colors reverted to original
        AppState-->>User: TUI reverts to<br/>original theme
    end
Loading

Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

4 files reviewed, no comments

Edit Code Review Agent Settings | Greptile

- Add preview_theme field to AppState for temporary theme previews
- Add set_preview_theme, get_effective_theme_colors, start_theme_preview,
  cancel_theme_preview, and confirm_theme_preview methods
- Add ModalResult::ActionContinue for live preview without closing modal
- Add ModalAction variants: PreviewTheme, RevertTheme, ConfirmTheme
- Update ThemeSelectorModal to emit preview actions on navigation
- Add color swatch display in theme selector rows
- Handle new theme actions in event loop
- Update ThemePicker to use ThemeSelectorModal instead of interactive builder
- Add comprehensive tests for new preview functionality
@echobt echobt force-pushed the feat/live-theme-preview branch from aa6f3a5 to abe702a Compare February 5, 2026 13:39
@echobt echobt changed the title feat(tui): implement live theme preview system with dynamic colors feat(tui): implement live theme preview system Feb 5, 2026
@echobt echobt merged commit aac026f into main Feb 5, 2026
15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant