mirror of
https://github.com/openai/codex.git
synced 2026-11-08 20:40:33 +00:00
## Why Theme colors and dimmed text can lose contrast against terminal and shaded backgrounds. Pickers also need to keep controls and the selected result visible when space is limited. ## What changed - Add shared blue accents and contrast-aware foregrounds that account for painted backgrounds and terminal color depth, with terminal-default fallbacks for limited palettes. - Apply readable colors to footer text, status lines, prompt attachment labels, and diff content. Remove dimming from syntax-highlighted diff text so it does not undo contrast correction. - Use compact shortcut labels such as `ctrl+c`, emphasize complete key combinations, and separate composer footer actions with ` · `. - Add an opt-in picker presentation with full-width selection, filled tabs, separate overflow indicators, and navigation based on visible rows. Enable it for `/keymap`, reserving result space to keep controls stable across filtering and tab changes. ## Testing Add regression tests and snapshots for contrast after palette conversion, shaded diff backgrounds, shortcut typography, picker resizing and pagination, Unicode tab truncation, and stable `/keymap` geometry. GitOrigin-RevId: f3c71879d3bcc4e3b29d70e63cf377dea5914916
86 lines
2.9 KiB
Rust
86 lines
2.9 KiB
Rust
//! Filled tabs preserve active visibility and Unicode clipping on narrow terminals.
|
|
|
|
use super::*;
|
|
use pretty_assertions::assert_eq;
|
|
use ratatui::style::Color;
|
|
use ratatui::style::Modifier;
|
|
use ratatui::style::Style;
|
|
|
|
fn rendered_strip(labels: &[&str], active_idx: usize, width: u16) -> (String, Buffer) {
|
|
let area = Rect::new(/*x*/ 0, /*y*/ 0, width, /*height*/ 1);
|
|
let mut buf = Buffer::empty(area);
|
|
buf.set_style(
|
|
area,
|
|
Style::default().red().bg(Color::Yellow).underlined().dim(),
|
|
);
|
|
render_filled_tab_bar(labels, active_idx, area, &mut buf);
|
|
let text = (0..width).map(|x| buf[(x, 0)].symbol()).collect::<String>();
|
|
(text.trim_end().to_owned(), buf)
|
|
}
|
|
|
|
#[test]
|
|
fn filled_tabs_window_around_active_tab() {
|
|
crate::terminal_palette::with_test_default_colors(
|
|
crate::terminal_probe::DefaultColors {
|
|
fg: (30, 30, 30),
|
|
bg: (255, 255, 255),
|
|
},
|
|
|| {
|
|
let labels = [
|
|
"All",
|
|
"Common",
|
|
"Customized (3)",
|
|
"Unbound (4)",
|
|
"App",
|
|
"Composer",
|
|
"Debug",
|
|
];
|
|
let strips =
|
|
[0, 2, 6].map(|active_idx| rendered_strip(&labels, active_idx, /*width*/ 30).0);
|
|
insta::assert_snapshot!(strips.join("\n"));
|
|
for active_idx in 0..labels.len() {
|
|
let (text, buf) = rendered_strip(&labels, active_idx, /*width*/ 30);
|
|
assert!(text.contains(labels[active_idx]), "{text}");
|
|
let focused = buf
|
|
.content()
|
|
.iter()
|
|
.filter(|cell| cell.bg == active_tab_style().bg.unwrap())
|
|
.map(|cell| {
|
|
assert_eq!(cell.modifier, Modifier::BOLD);
|
|
cell.symbol()
|
|
})
|
|
.collect::<String>();
|
|
assert_eq!(focused, format!(" {} ", labels[active_idx]));
|
|
}
|
|
},
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn filled_tabs_truncate_unicode_without_hiding_active_tab() {
|
|
let labels = ["All", "文件系统 plugins", "Debug"];
|
|
let strips = [1, 4, 9, 16].map(|width| rendered_strip(&labels, /*active_idx*/ 1, width).0);
|
|
insta::assert_snapshot!(strips.join("\n"));
|
|
}
|
|
|
|
// Non-Windows tests have an unprobed default palette; Windows retains its console probe.
|
|
#[cfg(not(windows))]
|
|
#[test]
|
|
fn filled_tab_unknown_palette_uses_readable_underlined_defaults() {
|
|
let (_, buf) = rendered_strip(&["All"], /*active_idx*/ 0, /*width*/ 5);
|
|
assert_eq!(
|
|
buf.content()
|
|
.iter()
|
|
.map(|cell| (cell.fg, cell.bg, cell.modifier))
|
|
.collect::<Vec<_>>(),
|
|
vec![
|
|
(
|
|
Color::Reset,
|
|
Color::Reset,
|
|
Modifier::BOLD | Modifier::UNDERLINED
|
|
);
|
|
5
|
|
],
|
|
);
|
|
}
|