Skip to content

feat(theme): add Matrix films inspired theme and improve theme_picker…#2129

Open
malsony wants to merge 3 commits into
Hmbown:mainfrom
malsony:ui/theme
Open

feat(theme): add Matrix films inspired theme and improve theme_picker…#2129
malsony wants to merge 3 commits into
Hmbown:mainfrom
malsony:ui/theme

Conversation

@malsony
Copy link
Copy Markdown

@malsony malsony commented May 25, 2026

… logic

  • Add Matrix films inspired color scheme

  • Refactor theme_picker to use SELECTABLE_THEMES for last-theme lookup instead of hard-coding

Summary

Testing

  • cargo fmt --all -- --check
  • cargo clippy --workspace --all-targets --all-features
  • cargo test --workspace --all-features

Checklist

  • Updated docs or comments as needed
  • Added or updated tests where relevant
  • Verified TUI behavior manually if UI changes

Greptile Summary

This PR adds a Matrix-films-inspired green-on-black theme and refactors the ThemePickerView navigation to derive the last-theme index from SELECTABLE_THEMES rather than hard-coding ThemeId::GruvboxDark.

  • New MATRIX_UI_THEME constant and all supporting MATRIX_*_RGB palette entries are added to palette.rs; ThemeId::Matrix is registered in every relevant match arm, the SELECTABLE_THEMES slice, and normalize_theme_name (with the alias \"hacker\").
  • move_up/move_down are collapsed to single-expression modular arithmetic, the navigation test is updated to resolve the last entry dynamically, and a #[allow(clippy::too_many_arguments)] suppression is added to handle_view_events in ui.rs.

Confidence Score: 4/5

Safe to merge as a feature addition, but the Matrix theme ships with palette values that make parts of the UI invisible or indistinguishable.

The theme registration, picker refactor, and enum/match-arm additions are mechanically correct. The concern is in the Matrix palette itself: selection_bg and elevated_bg share the same colour (#003300) so row highlighting in any list is invisible, and several text-role colours sit far below readable contrast thresholds on the #000A00 surface.

crates/tui/src/palette.rs — the MATRIX_UI_THEME colour assignments need a second pass for contrast and role distinctiveness before the theme is production-ready.

Important Files Changed

Filename Overview
crates/tui/src/palette.rs Adds MATRIX_UI_THEME and all palette constants; several colour-role constants share identical values (MATRIX_TEXT_DIM_RGB == MATRIX_TEXT_HINT_RGB == #006600, MATRIX_SELECTION_RGB == MATRIX_ELEVATED_RGB == #003300), hardcoded #005500 in adapt_fg_for_theme, and missing trailing newline.
crates/tui/src/tui/theme_picker.rs move_up/move_down simplified to single-expression modular arithmetic; empty-list guard removed (SELECTABLE_THEMES is non-empty in practice); navigation test correctly updated to use SELECTABLE_THEMES.last().
crates/tui/src/config_ui.rs Adds Matrix variant to UiThemeValue enum and all match arms; test list updated correctly; trailing newline removed at EOF.
crates/tui/src/tui/ui.rs Adds #[allow(clippy::too_many_arguments)] to handle_view_events; a narrowly-scoped suppression that avoids a clippy lint on an unchanged signature.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[User opens /theme picker\nThemePickerView::new] --> B{original_name in\nSELECTABLE_THEMES?}
    B -- yes --> C[selected = matching index]
    B -- no --> D[selected = 0 / System]
    C & D --> E[Render modal\nwith live preview]

    E --> F{Keypress}
    F -- Up/k --> G["move_up()\n(selected + len - 1) % len"]
    F -- Down/j --> H["move_down()\n(selected + 1) % len"]
    F -- 1-9 --> I[Jump to index n-1\nif in bounds]
    F -- Home --> J[selected = 0]
    F -- End --> K[selected = len - 1]

    G & H & I & J & K --> L[Emit ConfigUpdated\npersist: false\nlive theme swap]
    L --> E

    F -- Enter --> M[EmitAndClose\npersist: true\nsave to settings.toml]
    F -- Esc --> N[EmitAndClose\npersist: false\nrestore original_name]
Loading

Fix All in Codex Fix All in Claude Code Fix All in Cursor

Reviews (2): Last reviewed commit: "Merge branch 'Hmbown:main' into ui/theme" | Re-trigger Greptile

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a new 'Matrix' theme to the TUI, adding the necessary color constants, theme definitions, and integration logic across the configuration and palette modules. Additionally, the theme picker's navigation logic was refactored for conciseness and its tests were updated to be more dynamic. Review feedback highlighted a readability issue with low-contrast reasoning text in the new theme and suggested adjusting background colors to better preserve visual separation between UI components.

Comment thread crates/tui/src/palette.rs
Comment on lines +951 to +955
if theme == ThemeId::Matrix {
Color::Rgb(0x00, 0x55, 0x00) // #005500
} else {
ui.mode_plan
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

high

The hardcoded color #005500 for reasoning text in the Matrix theme has very low contrast against the dark background (#000A00), making it difficult to read. Reasoning text is a primary content element and should be easily legible. Using a brighter green, such as the theme's mode_goal color, would significantly improve readability while maintaining the theme's aesthetic.

Suggested change
if theme == ThemeId::Matrix {
Color::Rgb(0x00, 0x55, 0x00) // #005500
} else {
ui.mode_plan
}
if theme == ThemeId::Matrix {
ui.mode_goal
} else {
ui.mode_plan
}

Copy link
Copy Markdown
Author

@malsony malsony May 25, 2026

Choose a reason for hiding this comment

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

The reasoning text is not fading to background, actually.

Comment thread crates/tui/src/palette.rs
Comment on lines +538 to +544
surface_bg: Color::Rgb(MATRIX_SURFACE_RGB.0, MATRIX_SURFACE_RGB.1, MATRIX_SURFACE_RGB.2),
panel_bg: Color::Rgb(MATRIX_SURFACE_RGB.0, MATRIX_SURFACE_RGB.1, MATRIX_SURFACE_RGB.2),
elevated_bg: Color::Rgb(MATRIX_ELEVATED_RGB.0, MATRIX_ELEVATED_RGB.1, MATRIX_ELEVATED_RGB.2),
composer_bg: Color::Rgb(MATRIX_SURFACE_RGB.0, MATRIX_SURFACE_RGB.1, MATRIX_SURFACE_RGB.2),
selection_bg: Color::Rgb(MATRIX_SELECTION_RGB.0, MATRIX_SELECTION_RGB.1, MATRIX_SELECTION_RGB.2),
header_bg: Color::Rgb(MATRIX_SURFACE_RGB.0, MATRIX_SURFACE_RGB.1, MATRIX_SURFACE_RGB.2),
footer_bg: Color::Rgb(MATRIX_SURFACE_RGB.0, MATRIX_SURFACE_RGB.1, MATRIX_SURFACE_RGB.2),
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

The MATRIX_UI_THEME uses the same color (MATRIX_SURFACE_RGB) for surface_bg, panel_bg, composer_bg, header_bg, and footer_bg. This eliminates the visual separation between the sidebar, composer, and main transcript area, which is a core part of the TUI's layout design. Consider using a slightly different shade (e.g., MATRIX_ELEVATED_RGB) for the panel and composer backgrounds to restore visual hierarchy.

malsony added 2 commits May 27, 2026 14:22
… logic

- Add Matrix films inspired color scheme

- Refactor theme_picker to use SELECTABLE_THEMES for last-theme lookup instead of hard-coding
Comment thread crates/tui/src/palette.rs
Comment on lines +85 to +86
pub const MATRIX_ELEVATED_RGB: (u8, u8, u8) = (0, 51, 0); // #003300
pub const MATRIX_SELECTION_RGB: (u8, u8, u8) = (0, 51, 0); // #003300
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 MATRIX_SELECTION_RGB and MATRIX_ELEVATED_RGB share the same hex value #003300. Because selection_bg and elevated_bg resolve to identical colours, a highlighted row in any list is visually indistinguishable from an elevated-panel background. The user receives no feedback when navigating the theme picker (or any other list) under the Matrix theme.

Suggested change
pub const MATRIX_ELEVATED_RGB: (u8, u8, u8) = (0, 51, 0); // #003300
pub const MATRIX_SELECTION_RGB: (u8, u8, u8) = (0, 51, 0); // #003300
pub const MATRIX_ELEVATED_RGB: (u8, u8, u8) = (0, 51, 0); // #003300
pub const MATRIX_SELECTION_RGB: (u8, u8, u8) = (0, 85, 0); // #005500

Fix in Codex Fix in Claude Code Fix in Cursor

Comment thread crates/tui/src/palette.rs
Comment thread crates/tui/src/palette.rs
Comment on lines 92 to 94
fn move_up(&mut self) {
let len = SELECTABLE_THEMES.len();
if len == 0 {
self.selected = 0;
} else if self.selected == 0 {
self.selected = len - 1;
} else {
self.selected -= 1;
}
self.selected = (self.selected + SELECTABLE_THEMES.len() - 1) % SELECTABLE_THEMES.len();
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 The refactored move_up uses unsigned arithmetic: if SELECTABLE_THEMES were ever empty (len == 0), 0 + 0 - 1 would underflow a usize and the subsequent % 0 would panic. The old code guarded this explicitly.

Suggested change
fn move_up(&mut self) {
let len = SELECTABLE_THEMES.len();
if len == 0 {
self.selected = 0;
} else if self.selected == 0 {
self.selected = len - 1;
} else {
self.selected -= 1;
}
self.selected = (self.selected + SELECTABLE_THEMES.len() - 1) % SELECTABLE_THEMES.len();
}
fn move_up(&mut self) {
let len = SELECTABLE_THEMES.len();
if len > 0 {
self.selected = (self.selected + len - 1) % len;
}
}

Fix in Codex Fix in Claude Code Fix in Cursor

Comment thread crates/tui/src/palette.rs
@@ -2060,4 +2125,4 @@ mod tests {
let _ = ColorDepth::detect();
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Missing newline at end of file. cargo fmt typically enforces a trailing newline; the absence here (also visible in config_ui.rs) will cause the cargo fmt --all -- --check step in the checklist to fail.

Fix in Codex Fix in Claude Code Fix in Cursor

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Oops, I thought I added a newline once, maybe it was "washed away" when I was trying to build and update... for several times...

@Hmbown
Copy link
Copy Markdown
Owner

Hmbown commented May 27, 2026

Independent review (Devin):

Matrix theme successfully implements the classic green-on-black terminal aesthetic with faithful color choices (#88FF88 for primary text, #000A00 surface). The theme picker improvements are independently valuable - better navigation logic and dynamic test coverage that adapts to the growing theme list.

Hard conflicts expected with sibling theme PRs (#2267 Claude, #2270 Solarized Light, #2276 terminal-transparent) as all append to SELECTABLE_THEMES. Will need coordinated merge order or conflict resolution when landing multiple themes together.

Note: Will conflict with v0.8.48 PR #2256 if it touches palette.rs.

@Hmbown
Copy link
Copy Markdown
Owner

Hmbown commented May 27, 2026

Theme cluster coordination — this PR is one of 4 in flight that all add to palette.rs::SELECTABLE_THEMES:

All 4 hard-conflict at the SELECTABLE_THEMES slice and normalize_theme_name arms. Plan: first-merged wins as-is; the other three each get a small rebase. Your palette + theme_picker improvements carry forward unchanged (the picker improvement is independently valuable beyond the Matrix theme itself — worth separating if it ends up easier).

Cross-pinging the cluster: @AiurArtanis @HUQIANTAO @Hmbown — same coordination note on each PR.

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.

2 participants