Improve UI spacing for queued messages (#9162)

Despite good spacing between queued messages and assistant message text:
<img width="462" height="322" alt="Screenshot 2026-01-12 at 4 54 50 PM"
src="https://github.com/user-attachments/assets/e8b46252-0b33-40d2-b431-cb73b9a3bd2e"
/>

Codex has confusing spacing between queued messages and shimmering
status text (making the queued message seem like a sub-item of the
shimmering status text)
<img width="615" height="217" alt="Screenshot 2026-01-12 at 4 54 18 PM"
src="https://github.com/user-attachments/assets/ee5e6095-8fe9-4863-88d2-10472cab8bd6"
/>

This PR changes the spacing between the queued message(s) and shimmering
status text to make it less confusing:
<img width="440" height="240" alt="Screenshot 2026-01-13 at 11 20 36 AM"
src="https://github.com/user-attachments/assets/02dcc690-cbe9-4943-87de-c7300ef51120"
/>

While working on the status/queued spacing change, we noticed two
paste‑burst tests were timing‑sensitive and could fail
on slower CI. We added a small test‑only helper to keep the paste‑burst
state active and refreshed during these tests. This
removes dependence on tight timing and makes the tests deterministic
without affecting runtime behavior.
This commit is contained in:
charley-oai 2026-01-20 14:54:49 -08:00 committed by GitHub
parent ca23b0da5b
commit 64678f895a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 176 additions and 13 deletions

View file

@ -701,11 +701,14 @@ impl BottomPane {
if !self.unified_exec_footer.is_empty() {
flex.push(0, RenderableItem::Borrowed(&self.unified_exec_footer));
}
let has_queued_messages = !self.queued_user_messages.messages.is_empty();
let has_status_or_footer =
self.status.is_some() || !self.unified_exec_footer.is_empty();
if has_queued_messages && has_status_or_footer {
flex.push(0, RenderableItem::Owned("".into()));
}
flex.push(1, RenderableItem::Borrowed(&self.queued_user_messages));
if self.status.is_some()
|| !self.unified_exec_footer.is_empty()
|| !self.queued_user_messages.messages.is_empty()
{
if !has_queued_messages && has_status_or_footer {
flex.push(0, RenderableItem::Owned("".into()));
}
let mut flex2 = FlexRenderable::new();
@ -951,6 +954,60 @@ mod tests {
);
}
#[test]
fn status_only_snapshot() {
let (tx_raw, _rx) = unbounded_channel::<AppEvent>();
let tx = AppEventSender::new(tx_raw);
let mut pane = BottomPane::new(BottomPaneParams {
app_event_tx: tx,
frame_requester: FrameRequester::test_dummy(),
has_input_focus: true,
enhanced_keys_supported: false,
placeholder_text: "Ask Codex to do anything".to_string(),
disable_paste_burst: false,
animations_enabled: true,
skills: Some(Vec::new()),
});
pane.set_task_running(true);
let width = 48;
let height = pane.desired_height(width);
let area = Rect::new(0, 0, width, height);
assert_snapshot!("status_only_snapshot", render_snapshot(&pane, area));
}
#[test]
fn status_with_details_and_queued_messages_snapshot() {
let (tx_raw, _rx) = unbounded_channel::<AppEvent>();
let tx = AppEventSender::new(tx_raw);
let mut pane = BottomPane::new(BottomPaneParams {
app_event_tx: tx,
frame_requester: FrameRequester::test_dummy(),
has_input_focus: true,
enhanced_keys_supported: false,
placeholder_text: "Ask Codex to do anything".to_string(),
disable_paste_burst: false,
animations_enabled: true,
skills: Some(Vec::new()),
});
pane.set_task_running(true);
pane.update_status(
"Working".to_string(),
Some("First detail line\nSecond detail line".to_string()),
);
pane.set_queued_user_messages(vec!["Queued follow-up question".to_string()]);
let width = 48;
let height = pane.desired_height(width);
let area = Rect::new(0, 0, width, height);
assert_snapshot!(
"status_with_details_and_queued_messages_snapshot",
render_snapshot(&pane, area)
);
}
#[test]
fn queued_messages_visible_when_status_hidden_snapshot() {
let (tx_raw, _rx) = unbounded_channel::<AppEvent>();

View file

@ -5,7 +5,6 @@ expression: "render_snapshot(&pane, area)"
↳ Queued follow-up question
⌥ + ↑ edit
Ask Codex to do anything
100% context left · ? for shortcuts

View file

@ -3,10 +3,10 @@ source: tui/src/bottom_pane/mod.rs
expression: "render_snapshot(&pane, area)"
---
• Working (0s • esc to interrupt)
↳ Queued follow-up question
⌥ + ↑ edit
Ask Codex to do anything
100% context left · ? for shortcuts

View file

@ -0,0 +1,10 @@
---
source: tui/src/bottom_pane/mod.rs
expression: "render_snapshot(&pane, area)"
---
• Working (0s • esc to interrupt)
Ask Codex to do anything
100% context left · ? for shortcuts

View file

@ -0,0 +1,14 @@
---
source: tui/src/bottom_pane/mod.rs
expression: "render_snapshot(&pane, area)"
---
• Working (0s • esc to interrupt)
└ First detail line
Second detail line
↳ Queued follow-up question
⌥ + ↑ edit
Ask Codex to do anything
100% context left · ? for shortcuts

View file

@ -2,7 +2,9 @@
source: tui/src/chatwidget/tests.rs
expression: term.backend().vt100().screen().contents()
---
• Working (0s • esc to interrupt)
↳ Hello, world! 0
↳ Hello, world! 1
↳ Hello, world! 2
@ -21,7 +23,6 @@ expression: term.backend().vt100().screen().contents()
↳ Hello, world! 15
↳ Hello, world! 16
Ask Codex to do anything
100% context left · ? for shortcuts

View file

@ -1,6 +1,5 @@
---
source: tui/src/chatwidget/tests.rs
assertion_line: 3840
expression: term.backend().vt100().screen().contents()
---
@ -14,10 +13,10 @@ expression: term.backend().vt100().screen().contents()
• Working (0s • esc to interrupt)
↳ Queued while /review is running.
⌥ + ↑ edit
Ask Codex to do anything
100% context left · ? for shortcuts

View file

@ -688,8 +688,13 @@ impl BottomPane {
if let Some(status) = &self.status {
flex.push(0, RenderableItem::Borrowed(status));
}
let has_queued_messages = !self.queued_user_messages.messages.is_empty();
let has_status = self.status.is_some();
if has_queued_messages && has_status {
flex.push(0, RenderableItem::Owned("".into()));
}
flex.push(1, RenderableItem::Borrowed(&self.queued_user_messages));
if self.status.is_some() || !self.queued_user_messages.messages.is_empty() {
if !has_queued_messages && has_status {
flex.push(0, RenderableItem::Owned("".into()));
}
let mut flex2 = FlexRenderable::new();
@ -931,6 +936,60 @@ mod tests {
);
}
#[test]
fn status_only_snapshot() {
let (tx_raw, _rx) = unbounded_channel::<AppEvent>();
let tx = AppEventSender::new(tx_raw);
let mut pane = BottomPane::new(BottomPaneParams {
app_event_tx: tx,
frame_requester: FrameRequester::test_dummy(),
has_input_focus: true,
enhanced_keys_supported: false,
placeholder_text: "Ask Codex to do anything".to_string(),
disable_paste_burst: false,
animations_enabled: true,
skills: Some(Vec::new()),
});
pane.set_task_running(true);
let width = 48;
let height = pane.desired_height(width);
let area = Rect::new(0, 0, width, height);
assert_snapshot!("status_only_snapshot", render_snapshot(&pane, area));
}
#[test]
fn status_with_details_and_queued_messages_snapshot() {
let (tx_raw, _rx) = unbounded_channel::<AppEvent>();
let tx = AppEventSender::new(tx_raw);
let mut pane = BottomPane::new(BottomPaneParams {
app_event_tx: tx,
frame_requester: FrameRequester::test_dummy(),
has_input_focus: true,
enhanced_keys_supported: false,
placeholder_text: "Ask Codex to do anything".to_string(),
disable_paste_burst: false,
animations_enabled: true,
skills: Some(Vec::new()),
});
pane.set_task_running(true);
pane.update_status(
"Working".to_string(),
Some("First detail line\nSecond detail line".to_string()),
);
pane.set_queued_user_messages(vec!["Queued follow-up question".to_string()]);
let width = 48;
let height = pane.desired_height(width);
let area = Rect::new(0, 0, width, height);
assert_snapshot!(
"status_with_details_and_queued_messages_snapshot",
render_snapshot(&pane, area)
);
}
#[test]
fn queued_messages_visible_when_status_hidden_snapshot() {
let (tx_raw, _rx) = unbounded_channel::<AppEvent>();

View file

@ -5,7 +5,6 @@ expression: "render_snapshot(&pane, area)"
↳ Queued follow-up question
⌥ + ↑ edit
Ask Codex to do anything
100% context left · ? for shortcuts

View file

@ -3,10 +3,10 @@ source: tui2/src/bottom_pane/mod.rs
expression: "render_snapshot(&pane, area)"
---
• Working (0s • esc to interrupt)
↳ Queued follow-up question
⌥ + ↑ edit
Ask Codex to do anything
100% context left · ? for shortcuts

View file

@ -0,0 +1,10 @@
---
source: tui2/src/bottom_pane/mod.rs
expression: "render_snapshot(&pane, area)"
---
• Working (0s • esc to interrupt)
Ask Codex to do anything
100% context left · ? for shortcuts

View file

@ -0,0 +1,14 @@
---
source: tui2/src/bottom_pane/mod.rs
expression: "render_snapshot(&pane, area)"
---
• Working (0s • esc to interrupt)
└ First detail line
Second detail line
↳ Queued follow-up question
⌥ + ↑ edit
Ask Codex to do anything
100% context left · ? for shortcuts

View file

@ -2,7 +2,9 @@
source: tui2/src/chatwidget/tests.rs
expression: term.backend().vt100().screen().contents()
---
• Working (0s • esc to interrupt)
↳ Hello, world! 0
↳ Hello, world! 1
↳ Hello, world! 2
@ -21,7 +23,6 @@ expression: term.backend().vt100().screen().contents()
↳ Hello, world! 15
↳ Hello, world! 16
Ask Codex to do anything
100% context left · ? for shortcuts