From 52fab678b6a6867ead30e10910a36cf045894bab Mon Sep 17 00:00:00 2001 From: SofiaAFigueredo Date: Wed, 21 Oct 2026 07:44:04 -0300 Subject: [PATCH] Scope the File page's back-arrow hit area to the chevron MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On Windows/Linux, the back arrow in the File (Backstage) page's side panel was clickable across the whole 200px-wide row, not just the chevron icon drawn at its left edge. Clicking anywhere in that row — plain sidebar background to a user's eye — closed the File page the same as clicking the arrow itself, with no visual cue it was clickable. Scope the click region to a narrow band around the chevron, the same width already used for the macOS chevron fix (#2972). The row still reserves its full 200x40 space for layout; only the interactive rect shrinks. Updated two tests that relied on the old oversized hit box to click at the chevron's actual position, and added a regression test asserting a click beside the arrow leaves the File page open. Co-Authored-By: Claude Sonnet 5 --- crates/ui-egui/src/backstage.rs | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/crates/ui-egui/src/backstage.rs b/crates/ui-egui/src/backstage.rs index ac07f8424f..c11cb93e90 100644 --- a/crates/ui-egui/src/backstage.rs +++ b/crates/ui-egui/src/backstage.rs @@ -63,14 +63,13 @@ pub fn show(app: &mut WordApp, ui: &mut Ui) { icons::paint(ui.painter(), Rect::from_center_size(c, vec2(18.0, 18.0)), "chevronLeft", egui::Color32::WHITE, egui::Color32::WHITE); resp } else { - let (r, resp) = ui.allocate_exact_size(vec2(200.0, 40.0), Sense::click()); - icons::paint( - ui.painter(), - Rect::from_center_size(pos2(r.min.x + 26.0, r.center().y), vec2(18.0, 18.0)), - "chevronLeft", - egui::Color32::WHITE, - egui::Color32::WHITE, - ); + // The hit area is scoped to the chevron, not the whole 200px-wide row (#3041): + // the row reads as plain sidebar background next to it, so clicking there must + // not also close the File page, same as the macOS chevron fix (#2972) below. + let (r, _) = ui.allocate_exact_size(vec2(200.0, 40.0), Sense::hover()); + let c = pos2(r.min.x + 26.0, r.center().y); + let resp = ui.interact(Rect::from_center_size(c, vec2(22.0, r.height())), ui.id().with("backstage_back"), Sense::click()); + icons::paint(ui.painter(), Rect::from_center_size(c, vec2(18.0, 18.0)), "chevronLeft", egui::Color32::WHITE, egui::Color32::WHITE); resp }; // Escape in the built-in file browser closes only the browser. @@ -742,7 +741,7 @@ mod tests { h.state_mut().run("ui.backstage", json!({"value": true})).unwrap(); h.run_steps(4); // The arrow heads the File page's side bar; it has no label to find it by. - let arrow = egui::pos2(100.0, 32.0); + let arrow = egui::pos2(26.0, 32.0); h.event(egui::Event::PointerMoved(arrow)); for pressed in [true, false] { h.event(egui::Event::PointerButton { pos: arrow, button: egui::PointerButton::Primary, pressed, modifiers: egui::Modifiers::NONE }); @@ -752,6 +751,19 @@ mod tests { assert!(h.state().canvas.focused, "and the page has the keyboard"); } + /// #3041: clicking the plain sidebar background next to the back arrow must not also close + /// the File page — only the chevron itself does, same scoping as the macOS chevron (#2972). + #[test] + fn clicking_beside_the_back_arrow_does_not_close_the_file_page() { + let a = WordApp::new(wordcraft_engine::Session::new(wordcraft_doc::Document::new()), Services::default()); + let mut h = a11y_harness(a); + h.state_mut().run("ui.backstage", json!({"value": true})).unwrap(); + h.run_steps(4); + // Well clear of the chevron (centred at x=26) but still inside the old 200px-wide row. + click_at(&mut h, egui::pos2(100.0, 32.0)); + assert!(h.state().ui.backstage, "clicking beside the arrow leaves the File page open"); + } + /// A harness over the whole app; kittest always runs AccessKit, so a frame that names as /// focused a widget it didn't draw panics with "Focused ID … is not in the node list". fn a11y_harness(a: WordApp) -> egui_kittest::Harness<'static, WordApp> { @@ -848,7 +860,7 @@ mod tests { a.ui.start_screen = true; assert!(a.start_screen()); } - let back = if mac { mac_chevron(&a) } else { egui::pos2(100.0, 32.0) }; + let back = if mac { mac_chevron(&a) } else { egui::pos2(26.0, 32.0) }; let mut h = a11y_harness(a); if !start { h.state_mut().run("ui.backstage", json!({"value": true})).unwrap();