Use consistent ordering for popup menus (#27765)

Before this change, the editor completion menu and gutter menus reversed their order so that the initial selection is near the user's focus.  This change instead displays these menus in a consistent top-to-bottom order because the following benefits outweigh that benefit:

* Matches behavior of some other editors (Neovim and VSCode).
* Looks better for lexicographic lists.
* Keeps the meaning of keyboard interaction consistent, if the user is anticipating the order of the menu's contents.

Could consider making this configurable in the future if desired.

Closes #25066.

Release Notes:

- N/A
This commit is contained in:
Aaron Feickert 2025-04-04 15:57:09 -05:00 committed by GitHub
parent f3adf41c25
commit 7bc62de267
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 7 additions and 14 deletions

View file

@ -126,16 +126,15 @@ impl CodeContextMenu {
&self,
style: &EditorStyle,
max_height_in_lines: u32,
y_flipped: bool,
window: &mut Window,
cx: &mut Context<Editor>,
) -> AnyElement {
match self {
CodeContextMenu::Completions(menu) => {
menu.render(style, max_height_in_lines, y_flipped, window, cx)
menu.render(style, max_height_in_lines, window, cx)
}
CodeContextMenu::CodeActions(menu) => {
menu.render(style, max_height_in_lines, y_flipped, window, cx)
menu.render(style, max_height_in_lines, window, cx)
}
}
}
@ -439,7 +438,6 @@ impl CompletionsMenu {
&self,
style: &EditorStyle,
max_height_in_lines: u32,
y_flipped: bool,
window: &mut Window,
cx: &mut Context<Editor>,
) -> AnyElement {
@ -589,7 +587,6 @@ impl CompletionsMenu {
.occlude()
.max_h(max_height_in_lines as f32 * window.line_height())
.track_scroll(self.scroll_handle.clone())
.y_flipped(y_flipped)
.with_width_from_item(widest_completion_ix)
.with_sizing_behavior(ListSizingBehavior::Infer);
@ -978,7 +975,6 @@ impl CodeActionsMenu {
&self,
_style: &EditorStyle,
max_height_in_lines: u32,
y_flipped: bool,
window: &mut Window,
cx: &mut Context<Editor>,
) -> AnyElement {
@ -1068,7 +1064,6 @@ impl CodeActionsMenu {
.occlude()
.max_h(max_height_in_lines as f32 * window.line_height())
.track_scroll(self.scroll_handle.clone())
.y_flipped(y_flipped)
.with_width_from_item(
self.actions
.iter()

View file

@ -7702,7 +7702,6 @@ impl Editor {
&self,
style: &EditorStyle,
max_height_in_lines: u32,
y_flipped: bool,
window: &mut Window,
cx: &mut Context<Editor>,
) -> Option<AnyElement> {
@ -7711,7 +7710,7 @@ impl Editor {
if !menu.visible() {
return None;
};
Some(menu.render(style, max_height_in_lines, y_flipped, window, cx))
Some(menu.render(style, max_height_in_lines, window, cx))
}
fn render_context_menu_aside(

View file

@ -3351,7 +3351,7 @@ impl EditorElement {
height - height_above_menu
};
let mut element = self
.render_context_menu(line_height, menu_height, y_flipped, window, cx)
.render_context_menu(line_height, menu_height, window, cx)
.expect("Visible context menu should always render.");
let size = element.layout_as_root(AvailableSpace::min_size(), window, cx);
Some((CursorPopoverType::CodeContextMenu, element, size))
@ -3508,9 +3508,9 @@ impl EditorElement {
viewport_bounds,
window,
cx,
move |height, _max_width_for_stable_x, y_flipped, window, cx| {
move |height, _max_width_for_stable_x, _, window, cx| {
let mut element = self
.render_context_menu(line_height, height, y_flipped, window, cx)
.render_context_menu(line_height, height, window, cx)
.expect("Visible context menu should always render.");
let size = element.layout_as_root(AvailableSpace::min_size(), window, cx);
vec![(CursorPopoverType::CodeContextMenu, element, size)]
@ -3740,13 +3740,12 @@ impl EditorElement {
&self,
line_height: Pixels,
height: Pixels,
y_flipped: bool,
window: &mut Window,
cx: &mut App,
) -> Option<AnyElement> {
let max_height_in_lines = ((height - POPOVER_Y_PADDING) / line_height).floor() as u32;
self.editor.update(cx, |editor, cx| {
editor.render_context_menu(&self.style, max_height_in_lines, y_flipped, window, cx)
editor.render_context_menu(&self.style, max_height_in_lines, window, cx)
})
}