diff --git a/crates/nyaterm-desktop/src/features/panels/quick_command_editor_overlay.rs b/crates/nyaterm-desktop/src/features/panels/quick_command_editor_overlay.rs index 8a577b4bf..94fd5802b 100644 --- a/crates/nyaterm-desktop/src/features/panels/quick_command_editor_overlay.rs +++ b/crates/nyaterm-desktop/src/features/panels/quick_command_editor_overlay.rs @@ -1,8 +1,8 @@ use rust_i18n::t; use gpui::{ - AnyElement, App, ClickEvent, Context, FontWeight, IntoElement, KeyDownEvent, SharedString, - Window, div, prelude::*, px, rgb, rgba, svg, + AnyElement, App, ClickEvent, Context, FontWeight, IntoElement, KeyDownEvent, Rgba, + SharedString, Window, div, prelude::*, px, rgb, rgba, svg, }; use nyaterm_core::truncate_preview; use nyaterm_ui::{ @@ -708,6 +708,23 @@ impl NyaTermApp { } } +/// Fill for a category choice row. Selected rows use a wash built from the theme +/// primary color so they stay legible on both light and dark surfaces; hovering +/// deepens that wash instead of replacing it with the neutral hover color. +fn quick_command_category_choice_fill( + palette: crate::theme::ThemePalette, + selected: bool, + hovered: bool, +) -> Rgba { + if selected { + rgba((palette.primary << 8) | if hovered { 0x29 } else { 0x1f }) + } else if hovered { + rgb(palette.hover) + } else { + rgb(palette.surface) + } +} + fn quick_command_category_choice( palette: crate::theme::ThemePalette, id: String, @@ -720,11 +737,7 @@ fn quick_command_category_choice( .h(px(36.)) .w_full() .px_3() - .bg(if selected { - rgb(0x1d3357) - } else { - rgb(palette.surface) - }) + .bg(quick_command_category_choice_fill(palette, selected, false)) .cursor_pointer() .flex() .items_center() @@ -736,7 +749,7 @@ fn quick_command_category_choice( } else { rgb(palette.text) }) - .hover(|style| style.bg(rgb(palette.hover))) + .hover(move |style| style.bg(quick_command_category_choice_fill(palette, selected, true))) .child(div().min_w_0().text_ellipsis().child(label)) .when(selected, |this| { this.child( @@ -813,3 +826,43 @@ fn quick_command_icon_option( 16., )) } + +#[cfg(test)] +mod tests { + use gpui::{rgb, rgba}; + + use super::quick_command_category_choice_fill; + use crate::theme::theme_palette; + + #[test] + fn category_choice_fill_uses_theme_tokens_for_each_state() { + for id in ["github-dark", "github-light"] { + let palette = theme_palette(id); + assert_eq!( + quick_command_category_choice_fill(palette, true, false), + rgba((palette.primary << 8) | 0x1f), + "{id}: selected fill should be the theme primary wash", + ); + assert_eq!( + quick_command_category_choice_fill(palette, true, true), + rgba((palette.primary << 8) | 0x29), + "{id}: selected hover should deepen the primary wash", + ); + assert_eq!( + quick_command_category_choice_fill(palette, false, false), + rgb(palette.surface), + "{id}: idle fill should be the theme surface", + ); + assert_eq!( + quick_command_category_choice_fill(palette, false, true), + rgb(palette.hover), + "{id}: hover fill should be the theme hover token", + ); + } + // Light and dark appearances must resolve different selected fills. + assert_ne!( + quick_command_category_choice_fill(theme_palette("github-dark"), true, false), + quick_command_category_choice_fill(theme_palette("github-light"), true, false), + ); + } +}