1
0
mirror of https://github.com/emilk/egui.git synced 2026-08-29 04:40:03 -04:00

Fix menu keyboard toggle for open submenus (#7957)

Summary
This PR fixes submenu keyboard parity: pressing Enter/Space on an
already-open submenu button now collapses that submenu (matching
top-level menu button behavior).

What changed
Updated submenu interaction logic to distinguish pointer primary clicks
from keyboard/accessibility-triggered clicks.
Kept pointer/touch behavior unchanged (submenu button clicks still don’t
auto-close submenu).
Added regression tests for:
keyboard open of nested submenu,
keyboard close (second Enter) of nested submenu,
pointer clicks on submenu button keeping submenu open.


Validation
cargo test -p egui_kittest --test regression_tests

Breaking changes
None. Behavior change is limited to keyboard/accessibility activation of
already-open submenu buttons.

* Closes <https://github.com/emilk/egui/issues/7926> 
* [ X ] I have followed the instructions in the PR template

---------

Co-authored-by: Lucas Meurer <hi@lucasmerlin.me>
This commit is contained in:
Frank
2026-03-24 08:03:00 -05:00
committed by GitHub
parent 8137aa350c
commit 405eb81578
2 changed files with 113 additions and 2 deletions

View File

@@ -262,3 +262,101 @@ pub fn menus_should_close_even_if_submenu_disappears() {
);
}
}
fn keyboard_submenu_harness() -> Harness<'static, bool> {
Harness::builder()
.with_size(Vec2::new(400.0, 240.0))
.build_ui_state(
|ui, checked| {
egui::Panel::top("menu_bar").show_inside(ui, |ui| {
egui::MenuBar::new().ui(ui, |ui| {
ui.menu_button("X", |ui| {
ui.menu_button("Y", |ui| {
ui.checkbox(checked, "Goal");
});
});
});
});
},
false,
)
}
#[test]
pub fn keyboard_should_open_nested_submenu() {
let mut harness = keyboard_submenu_harness();
harness.get_by_label("X").focus();
harness.run();
harness.key_press(egui::Key::Enter);
harness.run();
harness.get_by_label_contains("Y").focus();
harness.run();
harness.key_press(egui::Key::Enter);
harness.run();
assert!(
harness.query_by_label("Goal").is_some(),
"Expected nested submenu to open via keyboard"
);
}
#[test]
pub fn keyboard_should_close_nested_submenu_with_second_enter() {
let mut harness = keyboard_submenu_harness();
harness.get_by_label("X").focus();
harness.run();
harness.key_press(egui::Key::Enter);
harness.run();
harness.get_by_label_contains("Y").focus();
harness.run();
harness.key_press(egui::Key::Enter);
harness.run();
assert!(
harness.query_by_label("Goal").is_some(),
"Expected nested submenu to open before close attempt"
);
harness.get_by_label_contains("Y").focus();
harness.run();
harness.key_press(egui::Key::Enter);
harness.run();
assert!(
harness.query_by_label("Goal").is_none(),
"Expected nested submenu to close when pressing Enter again"
);
}
#[test]
pub fn pointer_click_on_open_submenu_button_should_not_close_it() {
let mut harness = keyboard_submenu_harness();
harness.get_by_label("X").click();
harness.run();
harness.get_by_label_contains("Y").click();
harness.run();
assert!(
harness.query_by_label("Goal").is_some(),
"Expected submenu to remain open after pointer click on its button"
);
harness.get_by_label_contains("Y").click();
harness.run();
assert!(
harness.query_by_label("Goal").is_some(),
"Expected submenu to remain open on repeated pointer click"
);
}