Show left/right arrows to navigate in tui request_user_input (#10921)

<img width="785" height="185" alt="Screenshot 2026-02-06 at 10 25 13 AM"
src="https://github.com/user-attachments/assets/402a6e79-4626-4df9-b3da-bc2f28e64611"
/>

<img width="784" height="213" alt="Screenshot 2026-02-06 at 10 26 37 AM"
src="https://github.com/user-attachments/assets/cf9614b2-aa1e-4c61-8579-1d2c7e1c7dc1"
/>

"left/right to navigate questions" in request_user_input footer
This commit is contained in:
Charley Cunningham 2026-02-06 23:41:08 -08:00 committed by GitHub
parent 3779b52e2d
commit f3f35526a8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 117 additions and 7 deletions

View file

@ -443,10 +443,10 @@ impl RequestUserInputOverlay {
};
tips.push(enter_tip);
if question_count > 1 {
if is_last_question {
tips.push(FooterTip::new("ctrl + n first question"));
} else {
tips.push(FooterTip::new("ctrl + n next question"));
if self.has_options() && !self.focus_is_notes() {
tips.push(FooterTip::new("←/→ to navigate questions"));
} else if !self.has_options() {
tips.push(FooterTip::new("ctrl + p / ctrl + n change question"));
}
}
if !(self.has_options() && notes_visible) {
@ -1042,6 +1042,14 @@ impl BottomPaneView for RequestUserInputOverlay {
self.move_question(false);
return;
}
KeyEvent {
code: KeyCode::Left,
modifiers: KeyModifiers::NONE,
..
} if self.has_options() && matches!(self.focus, Focus::Options) => {
self.move_question(false);
return;
}
KeyEvent {
code: KeyCode::Char('l'),
modifiers: KeyModifiers::NONE,
@ -1050,6 +1058,14 @@ impl BottomPaneView for RequestUserInputOverlay {
self.move_question(true);
return;
}
KeyEvent {
code: KeyCode::Right,
modifiers: KeyModifiers::NONE,
..
} if self.has_options() && matches!(self.focus, Focus::Options) => {
self.move_question(true);
return;
}
_ => {}
}
@ -1643,6 +1659,97 @@ mod tests {
assert_eq!(overlay.current_index(), 0);
}
#[test]
fn left_right_move_between_questions_in_options() {
let (tx, _rx) = test_sender();
let mut overlay = RequestUserInputOverlay::new(
request_event(
"turn-1",
vec![
question_with_options("q1", "Pick one"),
question_with_options("q2", "Pick two"),
],
),
tx,
true,
false,
false,
);
assert_eq!(overlay.current_index(), 0);
overlay.handle_key_event(KeyEvent::from(KeyCode::Right));
assert_eq!(overlay.current_index(), 1);
overlay.handle_key_event(KeyEvent::from(KeyCode::Left));
assert_eq!(overlay.current_index(), 0);
}
#[test]
fn options_notes_focus_hides_question_navigation_tip() {
let (tx, _rx) = test_sender();
let mut overlay = RequestUserInputOverlay::new(
request_event(
"turn-1",
vec![
question_with_options("q1", "Pick one"),
question_with_options("q2", "Pick two"),
],
),
tx,
true,
false,
false,
);
let tips = overlay.footer_tips();
let tip_texts = tips.iter().map(|tip| tip.text.as_str()).collect::<Vec<_>>();
assert_eq!(
tip_texts,
vec![
"tab to add notes",
"enter to submit answer",
"←/→ to navigate questions",
"esc to interrupt",
]
);
overlay.handle_key_event(KeyEvent::from(KeyCode::Tab));
let tips = overlay.footer_tips();
let tip_texts = tips.iter().map(|tip| tip.text.as_str()).collect::<Vec<_>>();
assert_eq!(
tip_texts,
vec!["tab or esc to clear notes", "enter to submit answer",]
);
}
#[test]
fn freeform_shows_ctrl_p_and_ctrl_n_question_navigation_tip() {
let (tx, _rx) = test_sender();
let mut overlay = RequestUserInputOverlay::new(
request_event(
"turn-1",
vec![
question_with_options("q1", "Area"),
question_without_options("q2", "Goal"),
],
),
tx,
true,
false,
false,
);
overlay.move_question(true);
let tips = overlay.footer_tips();
let tip_texts = tips.iter().map(|tip| tip.text.as_str()).collect::<Vec<_>>();
assert_eq!(
tip_texts,
vec![
"enter to submit all",
"ctrl + p / ctrl + n change question",
"esc to interrupt",
]
);
}
#[test]
fn tab_opens_notes_when_option_selected() {
let (tx, _rx) = test_sender();

View file

@ -1,5 +1,6 @@
---
source: tui/src/bottom_pane/request_user_input/mod.rs
assertion_line: 2600
expression: "render_snapshot(&overlay, area)"
---
@ -11,4 +12,4 @@ expression: "render_snapshot(&overlay, area)"
3. Option 3 Third choice.
tab to add notes | enter to submit answer
ctrl + n next question | esc to interrupt
←/→ to navigate questions | esc to interrupt

View file

@ -1,5 +1,6 @@
---
source: tui/src/bottom_pane/request_user_input/mod.rs
assertion_line: 2744
expression: "render_snapshot(&overlay, area)"
---
@ -10,4 +11,4 @@ expression: "render_snapshot(&overlay, area)"
2. Option 2 Second choice.
3. Option 3 Third choice.
tab to add notes | enter to submit answer | ctrl + n next question | esc to interrupt
tab to add notes | enter to submit answer | ←/→ to navigate questions | esc to interrupt

View file

@ -1,5 +1,6 @@
---
source: tui/src/bottom_pane/request_user_input/mod.rs
assertion_line: 2770
expression: "render_snapshot(&overlay, area)"
---
@ -12,4 +13,4 @@ expression: "render_snapshot(&overlay, area)"
enter to submit all | ctrl + n first question | esc to interrupt
enter to submit all | ctrl + p / ctrl + n change question | esc to interrupt