Skip to content

feat(theme): add Solarized Light theme#2270

Open
AiurArtanis wants to merge 4 commits into
Hmbown:mainfrom
AiurArtanis:feat/theme-solarized-light
Open

feat(theme): add Solarized Light theme#2270
AiurArtanis wants to merge 4 commits into
Hmbown:mainfrom
AiurArtanis:feat/theme-solarized-light

Conversation

@AiurArtanis
Copy link
Copy Markdown

@AiurArtanis AiurArtanis commented May 27, 2026

Summary

#1605
配色=情绪价值
image

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

Adds a Solarized Light theme to the TUI — a well-known warm-ivory-background palette often praised for readability. The implementation follows the existing theme extension pattern: new palette constants, a PaletteMode::SolarizedLight variant, ThemeId::SolarizedLight, a Theme::solarized_light() token set, and fg/bg adaptation functions that mirror the existing light-palette adapters.

  • All new SOLARIZED_* constants are self-contained and do not modify existing LIGHT_TEXT_* constants; the new solarized_light_does_not_mutate_whale_light_text test verifies this explicitly.
  • The theme-picker test is made future-proof by replacing the hard-coded GruvboxDark wrap-around sentinel with SELECTABLE_THEMES.last().
  • The reasoning-surface background in the solarized adapter maps SURFACE_REASONING* to SOLARIZED_PANEL (same as tool panels), giving up the visual cue that distinguishes model-reasoning blocks from regular content areas in all other light/grayscale themes.

Confidence Score: 5/5

Safe to merge — the change is purely additive, touching only palette constants, a new PaletteMode variant, and a new ThemeId; existing themes are unaffected.

All new Solarized constants are independent from existing LIGHT_TEXT_* constants (confirmed by test), all enum match arms are exhaustive, and the feature integrates cleanly with the existing theme extension pattern. The only notable gap is that reasoning surfaces are rendered with the same background as regular panels, which slightly reduces visual feedback during model-reasoning steps, but this does not break any functionality.

crates/tui/src/palette.rs — specifically the adapt_bg_for_solarized_light_palette reasoning-surface mapping and the SOLARIZED_COMPOSER duplicate.

Important Files Changed

Filename Overview
crates/tui/src/palette.rs Adds all Solarized Light palette RGB tuples, Color constants, UiTheme, PaletteMode variant, ThemeId wiring, adapt_fg/adapt_bg functions, and new unit tests. The palette tokens are well-structured and isolated from existing LIGHT_TEXT_* constants.
crates/tui/src/deepseek_theme.rs Adds solarized_light() Theme constructor and wires it into the PaletteMode match. Token assignments look correct and follow the same structure as other light theme variants.
crates/tui/src/settings.rs Updates error messages and test assertions to include solarized-light. All mechanical, consistent with other themes.
crates/tui/src/tui/theme_picker.rs Makes the wrap-around keyboard navigation test generic using SELECTABLE_THEMES.last() instead of hard-coding GruvboxDark.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[User selects solarized-light] --> B[normalize_theme_name]
    B --> C[ThemeId::SolarizedLight]
    C --> D[SOLARIZED_LIGHT_UI_THEME]
    C --> F[Theme::solarized_light]
    H[render fg color] --> J[adapt_fg_for_solarized_light_palette]
    J --> K{color match}
    K -->|TEXT_BODY| L[SOLARIZED_TEXT_BODY]
    K -->|TEXT_MUTED| M[SOLARIZED_TEXT_MUTED]
    K -->|TEXT_HINT| N[SOLARIZED_TEXT_HINT]
    I[render bg color] --> U[adapt_bg_for_solarized_light_palette]
    U --> V{color match}
    V -->|DEEPSEEK_INK| W[SOLARIZED_SURFACE]
    V -->|SURFACE_PANEL| X[SOLARIZED_PANEL]
    V -->|SURFACE_REASONING| X
Loading

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

Reviews (5): Last reviewed commit: "test(theme): include solarized in valida..." | 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 "Solarized Light" theme to the TUI, adding its corresponding palette colors, UI theme definition, and integration into the theme selection and adaptation logic. The review feedback highlights a regression where existing "Whale Light" theme constants (LIGHT_TEXT_*) were modified to use Solarized Light values. Reverting these constants is recommended to preserve the original theme. Consequently, dedicated helper functions (adapt_fg_for_solarized_light_palette and adapt_bg_for_solarized_light_palette) should be implemented for the Solarized Light palette mode instead of delegating to the default light palette adaptation helpers.

Comment thread crates/tui/src/palette.rs Outdated
Comment thread crates/tui/src/palette.rs
Comment thread crates/tui/src/palette.rs
Comment thread crates/tui/src/palette.rs Outdated
Comment thread crates/tui/src/palette.rs Outdated
@AiurArtanis AiurArtanis force-pushed the feat/theme-solarized-light branch from bba6d13 to c4a2f40 Compare May 27, 2026 09:30
@Hmbown
Copy link
Copy Markdown
Owner

Hmbown commented May 27, 2026

Pushed one more maintainer follow-up in e7b79c331 to keep the settings validation surface in sync with the new Solarized Light theme. The failed macOS job was from tests still treating solarized as invalid and assuming Gruvbox was the last picker row.

Local verification:

  • CARGO_TARGET_DIR=/Volumes/VIXinSSD/whalebro/codewhale/target cargo test -p codewhale-tui theme_normalizes_supported_values_and_rejects_unknowns -- --nocapture
  • CARGO_TARGET_DIR=/Volumes/VIXinSSD/whalebro/codewhale/target cargo test -p codewhale-tui tui_prefs_validate_rejects_unknown_theme -- --nocapture
  • CARGO_TARGET_DIR=/Volumes/VIXinSSD/whalebro/codewhale/target cargo test -p codewhale-tui arrow_navigation_wraps_at_picker_edges -- --nocapture
  • RUSTFLAGS=-Dwarnings CARGO_TARGET_DIR=/Volumes/VIXinSSD/whalebro/codewhale/target cargo check -p codewhale-tui --all-features --locked
  • cargo fmt --all -- --check
  • git diff --check

Thanks again @AiurArtanis - this keeps the feature narrow and makes the validation/picker tests future-proof for the release candidate pass.

Copy link
Copy Markdown
Owner

@Hmbown Hmbown left a comment

Choose a reason for hiding this comment

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

Approved for the v0.8.48 candidate queue. CI and Greptile are clean after the Solarized validation-test follow-up in e7b79c331; the theme surface, settings aliases, and picker wraparound tests now line up. Thanks @AiurArtanis for the Solarized Light contribution.

@Hmbown
Copy link
Copy Markdown
Owner

Hmbown commented May 27, 2026

Independent review:

Merged onto origin/main: clean (no textual conflicts), cargo check -p codewhale-tui --all-features --locked passes in 25s on the merge result.

Palette accuracy: all 16 canonical Solarized values are correct — base03=#002b36, base3=#fdf6e3, yellow=#b58900, orange=#cb4b16, red=#dc322f, blue=#268bd2, cyan=#2aa198, green=#859900. Matches Ethan Schoonover's reference verbatim.

Wiring complete: ThemeId::SolarizedLight added to SELECTABLE_THEMES (palette.rs:1147), PaletteMode::SolarizedLight arm in deepseek_theme.rs:175, "solarized" alias normalizes to "solarized-light" in settings.rs:1157-1159 with rejection test at 2097. Greptile's earlier regression flag (LIGHT_TEXT_* mutation) is resolved — diff shows LIGHT_TEXT_BODY and SOLARIZED_TEXT_BODY are now distinct constants with an assert_ne! guarding them.

WCAG (informational, not blocking): body text on #fdf6e3 = 13.9:1, muted = 5.0:1 (AA pass). text_hint = 2.93:1, warning yellow = 2.98:1, accent blue = 3.41:1 — all below AA 4.5:1 but faithful to Solarized's "selective contrast" design, same trade-off the upstream spec ships.

v0.8.48 (#2256) compatibility: clean — #2256 does not touch palette.rs, theme_picker.rs, settings.rs, or deepseek_theme.rs. / sibling-PR conflict: textual conflict guaranteed with #2267 (Claude), #2276 (terminal-transparent), and #2129 (Matrix) — all four PRs append to the same SELECTABLE_THEMES slice and same normalize_theme_name match arm. Whichever merges first will force the other three to rebase the same two hunks.

@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 match arms. Plan: first-merged wins as-is; the other three each get a 5-min rebase to insert their entry post-first. Order doesn't change anyone's palette, just literal line position. Your contribution and tests carry forward intact regardless of order.

Cross-pinging the cluster: @AiurArtanis @HUQIANTAO @Hmbown @malsony — see 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