From 5bbf45a20abdbc135f0ad26ed6b60a5d1328558a Mon Sep 17 00:00:00 2001 From: aiongg Date: Sat, 24 Oct 2026 13:12:49 +0000 Subject: [PATCH] panes: a bottom pane dragged to a side previews the width it docks at --- crates/ui/src/panes/mod.rs | 15 +++++++++++---- crates/ui/src/panes/tests.rs | 19 +++++++++++++++++++ 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/crates/ui/src/panes/mod.rs b/crates/ui/src/panes/mod.rs index b50829f1..f0eb6676 100644 --- a/crates/ui/src/panes/mod.rs +++ b/crates/ui/src/panes/mod.rs @@ -534,13 +534,19 @@ impl PaneHost { } if content.movable(&s.pane) { - self.drag_out(ui.ctx(), &bar, s, edge, rect, bounds, memory, preview, style, requests); + // Docked at the host's left or right edge, the pane gets the width the side limits + // give its size: a bottom pane's height, not its width. + let (side_min, side_max) = self.limits(content, &s.pane, bounds.width()); + let side_width = + s.state.size.filter(|v| v.is_finite()).or(default.filter(|v| v.is_finite())).unwrap_or(side_min).clamp(side_min, side_max); + self.drag_out(ui.ctx(), &bar, s, edge, rect, side_width, bounds, memory, preview, style, requests); } rect } /// A docked pane's title dragged beyond [`DOCK_SNAP`] of the pane: dropped near the host's - /// left or right edge it docks there, elsewhere it floats under the pointer. + /// left or right edge it docks there `side_width` wide, elsewhere it floats under the + /// pointer. #[allow(clippy::too_many_arguments)] fn drag_out( &self, @@ -549,6 +555,7 @@ impl PaneHost { s: &Shown

, edge: Edge, rect: Rect, + side_width: f32, bounds: Rect, memory: &mut Memory, preview: &egui::Painter, @@ -592,8 +599,8 @@ impl PaneHost { return; } let shape = match target.map(|t| self.side(t)) { - Some(Side::Left) => Rect::from_x_y_ranges(bounds.left()..=bounds.left() + rect.width(), bounds.y_range()), - Some(_) => Rect::from_x_y_ranges(bounds.right() - rect.width()..=bounds.right(), bounds.y_range()), + Some(Side::Left) => Rect::from_x_y_ranges(bounds.left()..=bounds.left() + side_width, bounds.y_range()), + Some(_) => Rect::from_x_y_ranges(bounds.right() - side_width..=bounds.right(), bounds.y_range()), None => float, }; chrome::drop_preview(preview, shape.shrink(1.0), style.accent, true); diff --git a/crates/ui/src/panes/tests.rs b/crates/ui/src/panes/tests.rs index 6d449e66..bb433521 100644 --- a/crates/ui/src/panes/tests.rs +++ b/crates/ui/src/panes/tests.rs @@ -174,6 +174,25 @@ fn columns_sit_side_by_side_resize_and_move_to_end() { assert_eq!(edge(&h, Pane::Styles), L + 250.0); } +#[test] +fn a_bottom_pane_dragged_to_a_side_previews_the_width_it_docks_at() { + let mut app = App::new(&[Pane::Comments]); + app.states.insert(Pane::Comments, PaneState::docked(Edge::Bottom, 300.0)); + let mut h = harness(app); + let from = title(&h, Pane::Comments).center(); + let to = pos2(L + 10.0, 200.0); + hold(&mut h, from, to); + let previewed = h.output().shapes.iter().any(|clipped| match &clipped.shape { + egui::Shape::Rect(shape) => shape.rect.left() == L + 1.0 && shape.rect.width() == 298.0, + _ => false, + }); + assert!(previewed, "a 300 pt side pane"); + send(&mut h, vec![button(to, false)]); + h.run_steps(2); + assert_eq!(h.state().place(Pane::Comments), Place::Docked(Edge::Start)); + assert_eq!(edge(&h, Pane::Comments), L + 300.0); +} + #[test] fn title_dragged_out_floats_and_a_drop_near_an_edge_docks() { // Drag-out-to-float and the 32 pt edge snap follow wordcraft#2584.