fix(maestro): make TUI chrome contrast palette-controlled

This commit is contained in:
Miguel Palhas
2026-08-25 13:02:48 +01:00
parent 76eb3d1386
commit 4c3f65027d
+28 -4
View File
@@ -106,6 +106,10 @@ pub struct Palette {
pub card: Surface,
/// The surface the highlighted card swaps in.
pub selection: Surface,
/// Background for TUI-owned chrome outside cards. Fixed-RGB chrome must
/// paint this background too; otherwise its contrast depends on the
/// operator's terminal theme.
pub chrome_bg: Color,
/// Panel border while that panel holds focus.
pub border_focused: Color,
/// Panel border while it does not.
@@ -148,8 +152,9 @@ impl Palette {
awaiting: Color::Rgb(0xf2, 0xcc, 0x60),
error: Color::Rgb(0xff, 0x94, 0x92),
},
chrome_bg: Color::Rgb(0x14, 0x16, 0x1b),
border_focused: Color::Rgb(0x58, 0xa6, 0xff),
border_unfocused: Color::Rgb(0x30, 0x36, 0x3d),
border_unfocused: Color::Rgb(0x6b, 0x72, 0x80),
focus_accent: Color::Rgb(0x58, 0xa6, 0xff),
group_row: Color::Rgb(0x8f, 0xa3, 0xc8),
mode_normal_bg: Color::Rgb(0x58, 0xa6, 0xff),
@@ -172,15 +177,18 @@ impl Palette {
/// Border style for a panel, by whether it holds focus.
pub fn border_style(&self, focused: bool) -> Style {
if focused {
Style::default().fg(self.border_focused)
Style::default().bg(self.chrome_bg).fg(self.border_focused)
} else {
Style::default().fg(self.border_unfocused)
Style::default()
.bg(self.chrome_bg)
.fg(self.border_unfocused)
}
}
/// Style for a sidebar group heading.
pub fn group_row_style(&self) -> Style {
Style::default()
.bg(self.chrome_bg)
.fg(self.group_row)
.add_modifier(Modifier::BOLD)
}
@@ -200,7 +208,7 @@ impl Palette {
/// Style for error text outside a card.
pub fn error_style(&self) -> Style {
Style::default().fg(self.error_text)
Style::default().bg(self.chrome_bg).fg(self.error_text)
}
}
@@ -298,10 +306,13 @@ mod tests {
}
/// Other panels' roles are RGB too, so a preset swap moves all of them.
/// Foregrounds are checked against the chrome background they are
/// actually painted on; they must never rely on the terminal default.
#[test]
fn chrome_roles_are_rgb_values() {
let p = active();
for (name, color) in [
("chrome_bg", p.chrome_bg),
("border_focused", p.border_focused),
("border_unfocused", p.border_unfocused),
("focus_accent", p.focus_accent),
@@ -325,6 +336,19 @@ mod tests {
let ratio = contrast_ratio(fg, bg).unwrap();
assert!(ratio >= 4.5, "mode {name} contrast {ratio:.2} is below 4.5");
}
for (name, fg, floor) in [
("border_focused", p.border_focused, 3.0),
("border_unfocused", p.border_unfocused, 3.0),
("focus_accent", p.focus_accent, 3.0),
("group_row", p.group_row, 4.5),
("error_text", p.error_text, 4.5),
] {
let ratio = contrast_ratio(fg, p.chrome_bg).unwrap();
assert!(
ratio >= floor,
"{name} contrast {ratio:.2} is below {floor} on chrome_bg"
);
}
}
#[test]