Fix conversation selector popover menu offset (#22796)

Before, the conversation popover menu covered up what you were typing
because it wasn't offset properly.

Now it's offset properly, using the UI font size so the amount of offset
scales with the font size:

<img width="435" alt="Screenshot 2025-01-07 at 4 34 27 PM"
src="https://github.com/user-attachments/assets/55e40910-8cd4-4548-b4fb-521eb2845775"
/>
<img width="454" alt="Screenshot 2025-01-07 at 4 33 58 PM"
src="https://github.com/user-attachments/assets/30350489-09f1-4cb8-9f95-ed4ee87bc110"
/>
<img width="488" alt="Screenshot 2025-01-07 at 4 34 18 PM"
src="https://github.com/user-attachments/assets/de60d990-2bd9-418d-a616-56beb3e4aa8a"
/>

Release Notes:

- N/A *or* Added/Fixed/Improved ...
This commit is contained in:
Richard Feldman 2025-01-08 08:32:48 -05:00 committed by GitHub
parent 68e670bf54
commit 52f29b4a1f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 23 additions and 8 deletions

View file

@ -10,7 +10,7 @@ use language_model::{LanguageModelRegistry, LanguageModelRequestTool};
use language_model_selector::LanguageModelSelector; use language_model_selector::LanguageModelSelector;
use rope::Point; use rope::Point;
use settings::Settings; use settings::Settings;
use theme::ThemeSettings; use theme::{get_ui_font_size, ThemeSettings};
use ui::{ use ui::{
prelude::*, ButtonLike, ElevationIndex, KeyBinding, PopoverMenu, PopoverMenuHandle, prelude::*, ButtonLike, ElevationIndex, KeyBinding, PopoverMenu, PopoverMenuHandle,
SwitchWithLabel, SwitchWithLabel,
@ -276,7 +276,7 @@ impl Render for MessageEditor {
.anchor(gpui::Corner::BottomLeft) .anchor(gpui::Corner::BottomLeft)
.offset(gpui::Point { .offset(gpui::Point {
x: px(0.0), x: px(0.0),
y: px(-16.0), y: (-get_ui_font_size(cx) * 2) - px(4.0),
}) })
.with_handle(self.inline_context_picker_menu_handle.clone()), .with_handle(self.inline_context_picker_menu_handle.clone()),
) )

View file

@ -19,6 +19,7 @@ pub struct Anchored {
fit_mode: AnchoredFitMode, fit_mode: AnchoredFitMode,
anchor_position: Option<Point<Pixels>>, anchor_position: Option<Point<Pixels>>,
position_mode: AnchoredPositionMode, position_mode: AnchoredPositionMode,
offset: Option<Point<Pixels>>,
} }
/// anchored gives you an element that will avoid overflowing the window bounds. /// anchored gives you an element that will avoid overflowing the window bounds.
@ -30,6 +31,7 @@ pub fn anchored() -> Anchored {
fit_mode: AnchoredFitMode::SwitchAnchor, fit_mode: AnchoredFitMode::SwitchAnchor,
anchor_position: None, anchor_position: None,
position_mode: AnchoredPositionMode::Window, position_mode: AnchoredPositionMode::Window,
offset: None,
} }
} }
@ -47,6 +49,13 @@ impl Anchored {
self self
} }
/// Offset the final position by this amount.
/// Useful when you want to anchor to an element but offset from it, such as in PopoverMenu.
pub fn offset(mut self, offset: Point<Pixels>) -> Self {
self.offset = Some(offset);
self
}
/// Sets the position mode for this anchored element. Local will have this /// Sets the position mode for this anchored element. Local will have this
/// interpret its [`Anchored::position`] as relative to the parent element. /// interpret its [`Anchored::position`] as relative to the parent element.
/// While Window will have it interpret the position as relative to the window. /// While Window will have it interpret the position as relative to the window.
@ -129,6 +138,7 @@ impl Element for Anchored {
self.anchor_corner, self.anchor_corner,
size, size,
bounds, bounds,
self.offset,
); );
let limits = Bounds { let limits = Bounds {
@ -245,18 +255,22 @@ impl AnchoredPositionMode {
anchor_corner: Corner, anchor_corner: Corner,
size: Size<Pixels>, size: Size<Pixels>,
bounds: Bounds<Pixels>, bounds: Bounds<Pixels>,
offset: Option<Point<Pixels>>,
) -> (Point<Pixels>, Bounds<Pixels>) { ) -> (Point<Pixels>, Bounds<Pixels>) {
let offset = offset.unwrap_or_default();
match self { match self {
AnchoredPositionMode::Window => { AnchoredPositionMode::Window => {
let anchor_position = anchor_position.unwrap_or(bounds.origin); let anchor_position = anchor_position.unwrap_or(bounds.origin);
let bounds = Bounds::from_corner_and_size(anchor_corner, anchor_position, size); let bounds =
Bounds::from_corner_and_size(anchor_corner, anchor_position + offset, size);
(anchor_position, bounds) (anchor_position, bounds)
} }
AnchoredPositionMode::Local => { AnchoredPositionMode::Local => {
let anchor_position = anchor_position.unwrap_or_default(); let anchor_position = anchor_position.unwrap_or_default();
let bounds = Bounds::from_corner_and_size( let bounds = Bounds::from_corner_and_size(
anchor_corner, anchor_corner,
bounds.origin + anchor_position, bounds.origin + anchor_position + offset,
size, size,
); );
(anchor_position, bounds) (anchor_position, bounds)

View file

@ -254,13 +254,14 @@ impl<M: ManagedView> Element for PopoverMenu<M> {
let mut menu_layout_id = None; let mut menu_layout_id = None;
let menu_element = element_state.menu.borrow_mut().as_mut().map(|menu| { let menu_element = element_state.menu.borrow_mut().as_mut().map(|menu| {
let offset = self.resolved_offset(cx);
let mut anchored = anchored() let mut anchored = anchored()
.snap_to_window_with_margin(px(8.)) .snap_to_window_with_margin(px(8.))
.anchor(self.anchor); .anchor(self.anchor)
.offset(offset);
if let Some(child_bounds) = element_state.child_bounds { if let Some(child_bounds) = element_state.child_bounds {
anchored = anchored.position( anchored =
child_bounds.corner(self.resolved_attach()) + self.resolved_offset(cx), anchored.position(child_bounds.corner(self.resolved_attach()) + offset);
);
} }
let mut element = deferred(anchored.child(div().occlude().child(menu.clone()))) let mut element = deferred(anchored.child(div().occlude().child(menu.clone())))
.with_priority(1) .with_priority(1)