fix(tui): clarify footer shortcut overlay hints (#25625)

## Why

The TUI shortcut overlay used static labels for `Tab` and `Ctrl+C`, even
though both keys change behavior while a task is running. That made the
visible help misleading: idle `Tab` submits rather than queues, and
active-turn `Ctrl+C` interrupts rather than exits.

Closes #25531.
Closes #25564.

## What Changed

- Pass task-running state into the shortcut overlay renderer.
- Render `Tab` as `submit message` while idle and `queue message` while
work is running.
- Render `Ctrl+C` as `exit` while idle and `interrupt` while work is
running.
- Add snapshot coverage for the active-work shortcut overlay and update
idle overlay snapshots.

## How to Test

1. Start Codex and open the shortcut overlay with `?` while no task is
running.
2. Confirm the overlay shows `tab to submit message` and `ctrl + c to
exit`.
3. Start a task, then open or keep the shortcut overlay visible while
work is running.
4. Confirm the overlay shows `tab to queue message` and `ctrl + c to
interrupt`.
5. Type a follow-up prompt during active work and press `Tab`; confirm
it queues rather than submitting immediately.

Targeted tests:

- `just test -p codex-tui footer_snapshots`
- `just test -p codex-tui footer_mode_snapshots`

## Validation Notes

`just test -p codex-tui` currently has two unrelated guardian
feature-flag test failures on this base:

-
`app::tests::update_feature_flags_disabling_guardian_clears_manual_review_policy_without_history`
-
`app::tests::update_feature_flags_disabling_guardian_clears_review_policy_and_restores_default`

`just argument-comment-lint codex-rs/tui/src/bottom_pane/footer.rs`
could not run locally because the prebuilt wrapper requires `dotslash`;
the touched Rust diff was manually inspected for opaque positional
literals.
This commit is contained in:
Felipe Coury
2026-06-01 19:41:22 -03:00
committed by GitHub
parent 8d720feb69
commit 4e540b1076
7 changed files with 109 additions and 3 deletions

View File

@@ -3410,6 +3410,7 @@ impl ChatComposer {
esc_backtrack_hint: self.footer.esc_backtrack_hint,
use_shift_enter_hint: self.footer.use_shift_enter_hint,
is_task_running: self.is_task_running,
queue_submissions: self.queue_submissions,
quit_shortcut_key: self.footer.quit_shortcut_key,
collaboration_modes_enabled: self.collaboration_modes_enabled,
is_wsl,
@@ -4691,6 +4692,16 @@ mod tests {
},
);
snapshot_composer_state(
"footer_mode_shortcut_overlay_queue_submissions",
/*enhanced_keys_supported*/ true,
|composer| {
composer.set_queue_submissions(/*queue_submissions*/ true);
let _ = composer
.handle_key_event(KeyEvent::new(KeyCode::Char('?'), KeyModifiers::NONE));
},
);
snapshot_composer_state(
"footer_mode_ctrl_c_quit",
/*enhanced_keys_supported*/ true,

View File

@@ -68,6 +68,7 @@ pub(crate) struct FooterProps {
pub(crate) esc_backtrack_hint: bool,
pub(crate) use_shift_enter_hint: bool,
pub(crate) is_task_running: bool,
pub(crate) queue_submissions: bool,
pub(crate) collaboration_modes_enabled: bool,
pub(crate) is_wsl: bool,
/// Which key the user must press again to quit.
@@ -742,6 +743,8 @@ fn footer_from_props_lines(
let state = ShortcutsState {
use_shift_enter_hint: props.use_shift_enter_hint,
esc_backtrack_hint: props.esc_backtrack_hint,
is_task_running: props.is_task_running,
queue_submissions: props.queue_submissions,
is_wsl: props.is_wsl,
collaboration_modes_enabled: props.collaboration_modes_enabled,
key_hints,
@@ -864,6 +867,8 @@ fn footer_hint_items_line(items: &[(String, String)]) -> Line<'static> {
struct ShortcutsState {
use_shift_enter_hint: bool,
esc_backtrack_hint: bool,
is_task_running: bool,
queue_submissions: bool,
is_wsl: bool,
collaboration_modes_enabled: bool,
key_hints: FooterKeyHints,
@@ -1096,6 +1101,13 @@ impl ShortcutDescriptor {
}?;
let mut line = Line::from(vec![self.prefix.into(), key.into()]);
match self.id {
ShortcutId::QueueMessageTab => {
if state.is_task_running || state.queue_submissions {
line.push_span(" to queue message");
} else {
line.push_span(" to submit message");
}
}
ShortcutId::EditPrevious => {
if state.esc_backtrack_hint {
line.push_span(" again to edit previous message");
@@ -1107,6 +1119,13 @@ impl ShortcutDescriptor {
]);
}
}
ShortcutId::Quit => {
if state.is_task_running {
line.push_span(" to interrupt");
} else {
line.push_span(" to exit");
}
}
_ => line.push_span(self.label),
};
Some(line)
@@ -1542,6 +1561,7 @@ mod tests {
esc_backtrack_hint: false,
use_shift_enter_hint: false,
is_task_running: false,
queue_submissions: false,
collaboration_modes_enabled: false,
is_wsl: false,
quit_shortcut_key: key_hint::ctrl(KeyCode::Char('c')),
@@ -1559,6 +1579,7 @@ mod tests {
esc_backtrack_hint: true,
use_shift_enter_hint: true,
is_task_running: false,
queue_submissions: false,
collaboration_modes_enabled: false,
is_wsl: false,
quit_shortcut_key: key_hint::ctrl(KeyCode::Char('c')),
@@ -1579,6 +1600,7 @@ mod tests {
esc_backtrack_hint: false,
use_shift_enter_hint: false,
is_task_running: false,
queue_submissions: false,
collaboration_modes_enabled: true,
is_wsl: false,
quit_shortcut_key: key_hint::ctrl(KeyCode::Char('c')),
@@ -1589,6 +1611,24 @@ mod tests {
},
);
snapshot_footer(
"footer_shortcuts_running",
FooterProps {
mode: FooterMode::ShortcutOverlay,
esc_backtrack_hint: false,
use_shift_enter_hint: false,
is_task_running: true,
queue_submissions: false,
collaboration_modes_enabled: false,
is_wsl: false,
quit_shortcut_key: key_hint::ctrl(KeyCode::Char('c')),
status_line_value: None,
status_line_enabled: false,
key_hints: FooterKeyHints::default_bindings(),
active_agent_label: None,
},
);
snapshot_footer(
"footer_ctrl_c_quit_idle",
FooterProps {
@@ -1596,6 +1636,7 @@ mod tests {
esc_backtrack_hint: false,
use_shift_enter_hint: false,
is_task_running: false,
queue_submissions: false,
collaboration_modes_enabled: false,
is_wsl: false,
quit_shortcut_key: key_hint::ctrl(KeyCode::Char('c')),
@@ -1613,6 +1654,7 @@ mod tests {
esc_backtrack_hint: false,
use_shift_enter_hint: false,
is_task_running: true,
queue_submissions: false,
collaboration_modes_enabled: false,
is_wsl: false,
quit_shortcut_key: key_hint::ctrl(KeyCode::Char('c')),
@@ -1630,6 +1672,7 @@ mod tests {
esc_backtrack_hint: false,
use_shift_enter_hint: false,
is_task_running: false,
queue_submissions: false,
collaboration_modes_enabled: false,
is_wsl: false,
quit_shortcut_key: key_hint::ctrl(KeyCode::Char('c')),
@@ -1647,6 +1690,7 @@ mod tests {
esc_backtrack_hint: true,
use_shift_enter_hint: false,
is_task_running: false,
queue_submissions: false,
collaboration_modes_enabled: false,
is_wsl: false,
quit_shortcut_key: key_hint::ctrl(KeyCode::Char('c')),
@@ -1664,6 +1708,7 @@ mod tests {
esc_backtrack_hint: false,
use_shift_enter_hint: false,
is_task_running: true,
queue_submissions: false,
collaboration_modes_enabled: false,
is_wsl: false,
quit_shortcut_key: key_hint::ctrl(KeyCode::Char('c')),
@@ -1683,6 +1728,7 @@ mod tests {
esc_backtrack_hint: false,
use_shift_enter_hint: false,
is_task_running: false,
queue_submissions: false,
collaboration_modes_enabled: false,
is_wsl: false,
quit_shortcut_key: key_hint::ctrl(KeyCode::Char('c')),
@@ -1702,6 +1748,7 @@ mod tests {
esc_backtrack_hint: false,
use_shift_enter_hint: false,
is_task_running: true,
queue_submissions: false,
collaboration_modes_enabled: false,
is_wsl: false,
quit_shortcut_key: key_hint::ctrl(KeyCode::Char('c')),
@@ -1717,6 +1764,7 @@ mod tests {
esc_backtrack_hint: false,
use_shift_enter_hint: false,
is_task_running: false,
queue_submissions: false,
collaboration_modes_enabled: true,
is_wsl: false,
quit_shortcut_key: key_hint::ctrl(KeyCode::Char('c')),
@@ -1745,6 +1793,7 @@ mod tests {
esc_backtrack_hint: false,
use_shift_enter_hint: false,
is_task_running: true,
queue_submissions: false,
collaboration_modes_enabled: true,
is_wsl: false,
quit_shortcut_key: key_hint::ctrl(KeyCode::Char('c')),
@@ -1766,6 +1815,7 @@ mod tests {
esc_backtrack_hint: false,
use_shift_enter_hint: false,
is_task_running: false,
queue_submissions: false,
collaboration_modes_enabled: false,
is_wsl: false,
quit_shortcut_key: key_hint::ctrl(KeyCode::Char('c')),
@@ -1782,6 +1832,7 @@ mod tests {
esc_backtrack_hint: false,
use_shift_enter_hint: false,
is_task_running: true,
queue_submissions: false,
collaboration_modes_enabled: false,
is_wsl: false,
quit_shortcut_key: key_hint::ctrl(KeyCode::Char('c')),
@@ -1798,6 +1849,7 @@ mod tests {
esc_backtrack_hint: false,
use_shift_enter_hint: false,
is_task_running: false,
queue_submissions: false,
collaboration_modes_enabled: false,
is_wsl: false,
quit_shortcut_key: key_hint::ctrl(KeyCode::Char('c')),
@@ -1814,6 +1866,7 @@ mod tests {
esc_backtrack_hint: false,
use_shift_enter_hint: false,
is_task_running: false,
queue_submissions: false,
collaboration_modes_enabled: true,
is_wsl: false,
quit_shortcut_key: key_hint::ctrl(KeyCode::Char('c')),
@@ -1844,6 +1897,7 @@ mod tests {
esc_backtrack_hint: false,
use_shift_enter_hint: false,
is_task_running: false,
queue_submissions: false,
collaboration_modes_enabled: true,
is_wsl: false,
quit_shortcut_key: key_hint::ctrl(KeyCode::Char('c')),
@@ -1866,6 +1920,7 @@ mod tests {
esc_backtrack_hint: false,
use_shift_enter_hint: false,
is_task_running: false,
queue_submissions: false,
collaboration_modes_enabled: false,
is_wsl: false,
quit_shortcut_key: key_hint::ctrl(KeyCode::Char('c')),
@@ -1889,6 +1944,7 @@ mod tests {
esc_backtrack_hint: false,
use_shift_enter_hint: false,
is_task_running: false,
queue_submissions: false,
collaboration_modes_enabled: true,
is_wsl: false,
quit_shortcut_key: key_hint::ctrl(KeyCode::Char('c')),
@@ -1913,6 +1969,7 @@ mod tests {
esc_backtrack_hint: false,
use_shift_enter_hint: false,
is_task_running: false,
queue_submissions: false,
collaboration_modes_enabled: false,
is_wsl: false,
quit_shortcut_key: key_hint::ctrl(KeyCode::Char('c')),
@@ -1929,6 +1986,7 @@ mod tests {
esc_backtrack_hint: false,
use_shift_enter_hint: false,
is_task_running: false,
queue_submissions: false,
collaboration_modes_enabled: false,
is_wsl: false,
quit_shortcut_key: key_hint::ctrl(KeyCode::Char('c')),
@@ -1948,6 +2006,7 @@ mod tests {
esc_backtrack_hint: false,
use_shift_enter_hint: false,
is_task_running: false,
queue_submissions: false,
collaboration_modes_enabled: true,
is_wsl: false,
quit_shortcut_key: key_hint::ctrl(KeyCode::Char('c')),
@@ -2009,6 +2068,8 @@ mod tests {
.binding_for(ShortcutsState {
use_shift_enter_hint: false,
esc_backtrack_hint: false,
is_task_running: false,
queue_submissions: false,
is_wsl,
collaboration_modes_enabled: false,
key_hints: FooterKeyHints::default_bindings(),

View File

@@ -11,7 +11,7 @@ expression: terminal.backend()
" "
" "
" / for commands ! for shell commands "
" shift + enter for newline tab to queue message "
" shift + enter for newline tab to submit message "
" @ for file paths ctrl + v to paste images "
" ctrl + g to edit in external editor esc again to edit previous message "
" ctrl + r search history ctrl + c to exit "

View File

@@ -0,0 +1,21 @@
---
source: tui/src/bottom_pane/chat_composer.rs
expression: terminal.backend()
---
" "
" Ask Codex to do anything "
" "
" "
" "
" "
" "
" "
" / for commands ! for shell commands "
" shift + enter for newline tab to queue message "
" @ for file paths ctrl + v to paste images "
" ctrl + g to edit in external editor esc esc to edit previous message "
" ctrl + r search history ctrl + c to exit "
" ⌥ + , reasoning down ⌥ + . reasoning up "
" ctrl + t to view transcript "
" "
" customize shortcuts with /keymap "

View File

@@ -3,7 +3,7 @@ source: tui/src/bottom_pane/footer.rs
expression: terminal.backend()
---
" / for commands ! for shell commands "
" ctrl + j for newline tab to queue message "
" ctrl + j for newline tab to submit message "
" @ for file paths ctrl + v to paste images "
" ctrl + g to edit in external editor esc esc to edit previous message "
" ctrl + r search history ctrl + c to exit "

View File

@@ -0,0 +1,13 @@
---
source: tui/src/bottom_pane/footer.rs
expression: terminal.backend()
---
" / for commands ! for shell commands "
" ctrl + j for newline tab to queue message "
" @ for file paths ctrl + v to paste images "
" ctrl + g to edit in external editor esc esc to edit previous message "
" ctrl + r search history ctrl + c to interrupt "
" ⌥ + , reasoning down ⌥ + . reasoning up "
" ctrl + t to view transcript "
" "
" customize shortcuts with /keymap "

View File

@@ -3,7 +3,7 @@ source: tui/src/bottom_pane/footer.rs
expression: terminal.backend()
---
" / for commands ! for shell commands "
" shift + enter for newline tab to queue message "
" shift + enter for newline tab to submit message "
" @ for file paths ctrl + v to paste images "
" ctrl + g to edit in external editor esc again to edit previous message "
" ctrl + r search history ctrl + c to exit "