Tui: hide Code mode footer label (#10063)

Title
Hide Code mode footer label/cycle hint; add Plan footer-collapse
snapshots

Summary
- Keep Code mode internal naming but suppress the footer mode label +
cycle hint when Code is active.
- Only show the cycle hint when a non‑Code mode indicator is present.
- Add Plan-mode footer collapse snapshot coverage (empty + queued,
across widths) and update existing footer collapse snapshots for the new
Code behavior.

Notes
- The test run currently fails in codex-cloud-requirements on
origin/main due to a stale auth.mode field; no fix is included in this
PR to keep the diff minimal.

Codex author
`codex resume 019c0296-cfd4-7193-9b0a-6949048e4546`
This commit is contained in:
Charley Cunningham 2026-01-30 11:15:21 -08:00 committed by GitHub
parent ec4a2d07e4
commit 2d10aa6859
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
21 changed files with 237 additions and 27 deletions

View file

@ -2873,7 +2873,8 @@ impl ChatComposer {
}
ActivePopup::None => {
let footer_props = self.footer_props();
let show_cycle_hint = !footer_props.is_task_running;
let show_cycle_hint =
!footer_props.is_task_running && self.collaboration_mode_indicator.is_some();
let show_shortcuts_hint = match footer_props.mode {
FooterMode::ComposerEmpty => !self.is_in_paste_burst(),
FooterMode::QuitShortcutReminder
@ -3353,23 +3354,23 @@ mod tests {
fn setup_collab_footer(
composer: &mut ChatComposer,
context_percent: i64,
indicator: CollaborationModeIndicator,
indicator: Option<CollaborationModeIndicator>,
) {
composer.set_collaboration_modes_enabled(true);
composer.set_collaboration_mode_indicator(Some(indicator));
composer.set_collaboration_mode_indicator(indicator);
composer.set_context_window(Some(context_percent), None);
}
// Empty textarea, agent idle: shortcuts hint can show, and cycle hint is available.
// Empty textarea, agent idle: shortcuts hint can show, and cycle hint is hidden.
snapshot_composer_state_with_width("footer_collapse_empty_full", 120, true, |composer| {
setup_collab_footer(composer, 100, CollaborationModeIndicator::Code);
setup_collab_footer(composer, 100, None);
});
snapshot_composer_state_with_width(
"footer_collapse_empty_mode_cycle_with_context",
60,
true,
|composer| {
setup_collab_footer(composer, 100, CollaborationModeIndicator::Code);
setup_collab_footer(composer, 100, None);
},
);
snapshot_composer_state_with_width(
@ -3377,7 +3378,7 @@ mod tests {
44,
true,
|composer| {
setup_collab_footer(composer, 100, CollaborationModeIndicator::Code);
setup_collab_footer(composer, 100, None);
},
);
snapshot_composer_state_with_width(
@ -3385,13 +3386,47 @@ mod tests {
26,
true,
|composer| {
setup_collab_footer(composer, 100, CollaborationModeIndicator::Code);
setup_collab_footer(composer, 100, None);
},
);
// Empty textarea, plan mode idle: shortcuts hint and cycle hint are available.
snapshot_composer_state_with_width(
"footer_collapse_plan_empty_full",
120,
true,
|composer| {
setup_collab_footer(composer, 100, Some(CollaborationModeIndicator::Plan));
},
);
snapshot_composer_state_with_width(
"footer_collapse_plan_empty_mode_cycle_with_context",
60,
true,
|composer| {
setup_collab_footer(composer, 100, Some(CollaborationModeIndicator::Plan));
},
);
snapshot_composer_state_with_width(
"footer_collapse_plan_empty_mode_cycle_without_context",
44,
true,
|composer| {
setup_collab_footer(composer, 100, Some(CollaborationModeIndicator::Plan));
},
);
snapshot_composer_state_with_width(
"footer_collapse_plan_empty_mode_only",
26,
true,
|composer| {
setup_collab_footer(composer, 100, Some(CollaborationModeIndicator::Plan));
},
);
// Textarea has content, agent running, steer enabled: queue hint is shown.
snapshot_composer_state_with_width("footer_collapse_queue_full", 120, true, |composer| {
setup_collab_footer(composer, 98, CollaborationModeIndicator::Code);
setup_collab_footer(composer, 98, None);
composer.set_steer_enabled(true);
composer.set_task_running(true);
composer.set_text_content("Test".to_string(), Vec::new(), Vec::new());
@ -3401,7 +3436,7 @@ mod tests {
50,
true,
|composer| {
setup_collab_footer(composer, 98, CollaborationModeIndicator::Code);
setup_collab_footer(composer, 98, None);
composer.set_steer_enabled(true);
composer.set_task_running(true);
composer.set_text_content("Test".to_string(), Vec::new(), Vec::new());
@ -3412,7 +3447,7 @@ mod tests {
40,
true,
|composer| {
setup_collab_footer(composer, 98, CollaborationModeIndicator::Code);
setup_collab_footer(composer, 98, None);
composer.set_steer_enabled(true);
composer.set_task_running(true);
composer.set_text_content("Test".to_string(), Vec::new(), Vec::new());
@ -3423,7 +3458,7 @@ mod tests {
30,
true,
|composer| {
setup_collab_footer(composer, 98, CollaborationModeIndicator::Code);
setup_collab_footer(composer, 98, None);
composer.set_steer_enabled(true);
composer.set_task_running(true);
composer.set_text_content("Test".to_string(), Vec::new(), Vec::new());
@ -3434,7 +3469,64 @@ mod tests {
20,
true,
|composer| {
setup_collab_footer(composer, 98, CollaborationModeIndicator::Code);
setup_collab_footer(composer, 98, None);
composer.set_steer_enabled(true);
composer.set_task_running(true);
composer.set_text_content("Test".to_string(), Vec::new(), Vec::new());
},
);
// Textarea has content, plan mode active, agent running, steer enabled: queue hint + mode.
snapshot_composer_state_with_width(
"footer_collapse_plan_queue_full",
120,
true,
|composer| {
setup_collab_footer(composer, 98, Some(CollaborationModeIndicator::Plan));
composer.set_steer_enabled(true);
composer.set_task_running(true);
composer.set_text_content("Test".to_string(), Vec::new(), Vec::new());
},
);
snapshot_composer_state_with_width(
"footer_collapse_plan_queue_short_with_context",
50,
true,
|composer| {
setup_collab_footer(composer, 98, Some(CollaborationModeIndicator::Plan));
composer.set_steer_enabled(true);
composer.set_task_running(true);
composer.set_text_content("Test".to_string(), Vec::new(), Vec::new());
},
);
snapshot_composer_state_with_width(
"footer_collapse_plan_queue_message_without_context",
40,
true,
|composer| {
setup_collab_footer(composer, 98, Some(CollaborationModeIndicator::Plan));
composer.set_steer_enabled(true);
composer.set_task_running(true);
composer.set_text_content("Test".to_string(), Vec::new(), Vec::new());
},
);
snapshot_composer_state_with_width(
"footer_collapse_plan_queue_short_without_context",
30,
true,
|composer| {
setup_collab_footer(composer, 98, Some(CollaborationModeIndicator::Plan));
composer.set_steer_enabled(true);
composer.set_task_running(true);
composer.set_text_content("Test".to_string(), Vec::new(), Vec::new());
},
);
snapshot_composer_state_with_width(
"footer_collapse_plan_queue_mode_only",
20,
true,
|composer| {
setup_collab_footer(composer, 98, Some(CollaborationModeIndicator::Plan));
composer.set_steer_enabled(true);
composer.set_task_running(true);
composer.set_text_content("Test".to_string(), Vec::new(), Vec::new());

View file

@ -73,12 +73,12 @@ pub(crate) struct FooterProps {
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub(crate) enum CollaborationModeIndicator {
Plan,
Code,
PairProgramming,
Execute,
}
const MODE_CYCLE_HINT: &str = "shift+tab to cycle";
const FOOTER_CONTEXT_GAP_COLS: u16 = 1;
impl CollaborationModeIndicator {
fn label(self, show_cycle_hint: bool) -> String {
@ -89,7 +89,6 @@ impl CollaborationModeIndicator {
};
match self {
CollaborationModeIndicator::Plan => format!("Plan mode{suffix}"),
CollaborationModeIndicator::Code => format!("Code mode{suffix}"),
CollaborationModeIndicator::PairProgramming => {
format!("Pair Programming mode{suffix}")
}
@ -101,7 +100,6 @@ impl CollaborationModeIndicator {
let label = self.label(show_cycle_hint);
match self {
CollaborationModeIndicator::Plan => Span::from(label).magenta(),
CollaborationModeIndicator::Code => Span::from(label).dim(),
CollaborationModeIndicator::PairProgramming => Span::from(label).cyan(),
CollaborationModeIndicator::Execute => Span::from(label).dim(),
}
@ -475,7 +473,10 @@ pub(crate) fn can_show_left_with_context(area: Rect, left_width: u16, context_wi
let Some(context_x) = right_aligned_x(area, context_width) else {
return true;
};
let left_extent = FOOTER_INDENT_COLS as u16 + left_width;
if left_width == 0 {
return true;
}
let left_extent = FOOTER_INDENT_COLS as u16 + left_width + FOOTER_CONTEXT_GAP_COLS;
left_extent <= context_x.saturating_sub(area.x)
}

View file

@ -10,4 +10,4 @@ expression: terminal.backend()
" "
" "
" "
" ? for shortcuts · Code mode (shift+tab to cycle) 100% context left "
" ? for shortcuts 100% context left "

View file

@ -10,4 +10,4 @@ expression: terminal.backend()
" "
" "
" "
" Code mode (shift+tab to cycle) 100% context left "
" ? for shortcuts 100% context left "

View file

@ -10,4 +10,4 @@ expression: terminal.backend()
" "
" "
" "
" Code mode (shift+tab to cycle) "
" ? for shortcuts 100% context left "

View file

@ -10,4 +10,4 @@ expression: terminal.backend()
" "
" "
" "
" Code mode "
" 100% context left "

View file

@ -0,0 +1,13 @@
---
source: tui/src/bottom_pane/chat_composer.rs
expression: terminal.backend()
---
" "
" Ask Codex to do anything "
" "
" "
" "
" "
" "
" "
" ? for shortcuts · Plan mode (shift+tab to cycle) 100% context left "

View file

@ -0,0 +1,13 @@
---
source: tui/src/bottom_pane/chat_composer.rs
expression: terminal.backend()
---
" "
" Ask Codex to do anything "
" "
" "
" "
" "
" "
" "
" Plan mode (shift+tab to cycle) 100% context left "

View file

@ -0,0 +1,13 @@
---
source: tui/src/bottom_pane/chat_composer.rs
expression: terminal.backend()
---
" "
" Ask Codex to do anything "
" "
" "
" "
" "
" "
" "
" Plan mode (shift+tab to cycle) "

View file

@ -0,0 +1,13 @@
---
source: tui/src/bottom_pane/chat_composer.rs
expression: terminal.backend()
---
" "
" Ask Codex to do anythin "
" "
" "
" "
" "
" "
" "
" Plan mode "

View file

@ -0,0 +1,13 @@
---
source: tui/src/bottom_pane/chat_composer.rs
expression: terminal.backend()
---
" "
" Test "
" "
" "
" "
" "
" "
" "
" tab to queue message · Plan mode 98% context left "

View file

@ -0,0 +1,13 @@
---
source: tui/src/bottom_pane/chat_composer.rs
expression: terminal.backend()
---
" "
" Test "
" "
" "
" "
" "
" "
" "
" tab to queue message · Plan mode "

View file

@ -0,0 +1,13 @@
---
source: tui/src/bottom_pane/chat_composer.rs
expression: terminal.backend()
---
" "
" Test "
" "
" "
" "
" "
" "
" "
" Plan mode "

View file

@ -0,0 +1,13 @@
---
source: tui/src/bottom_pane/chat_composer.rs
expression: terminal.backend()
---
" "
" Test "
" "
" "
" "
" "
" "
" "
" tab to queue · Plan mode 98% context left "

View file

@ -0,0 +1,13 @@
---
source: tui/src/bottom_pane/chat_composer.rs
expression: terminal.backend()
---
" "
" Test "
" "
" "
" "
" "
" "
" "
" tab to queue · Plan mode "

View file

@ -10,4 +10,4 @@ expression: terminal.backend()
" "
" "
" "
" tab to queue message · Code mode 98% context left "
" tab to queue message 98% context left "

View file

@ -10,4 +10,4 @@ expression: terminal.backend()
" "
" "
" "
" tab to queue message · Code mode "
" tab to queue 98% context left "

View file

@ -10,4 +10,4 @@ expression: terminal.backend()
" "
" "
" "
" Code mode "
" tab to queue "

View file

@ -10,4 +10,4 @@ expression: terminal.backend()
" "
" "
" "
" tab to queue · Code mode 98% context left "
" tab to queue message 98% context left "

View file

@ -10,4 +10,4 @@ expression: terminal.backend()
" "
" "
" "
" tab to queue · Code mode "
" tab to queue message "

View file

@ -5313,7 +5313,7 @@ impl ChatWidget {
}
match self.active_mode_kind() {
ModeKind::Plan => Some(CollaborationModeIndicator::Plan),
ModeKind::Code => Some(CollaborationModeIndicator::Code),
ModeKind::Code => None,
ModeKind::PairProgramming => Some(CollaborationModeIndicator::PairProgramming),
ModeKind::Execute => Some(CollaborationModeIndicator::Execute),
ModeKind::Custom => None,