Fix flicker in short context menus that have documentation aside (#38074)

Menu items in the context menu component have the ability to display a
documentation aside popover. However, because this docs aside popover
was setup as a sibling flex container to the actual menu popover, if the
menu had a short amount of items and the docs popover is bigger than the
menu, this flickering would happen, making it essentially unusable:


https://github.com/user-attachments/assets/74956254-fff6-4c5c-9f79-02998c64a105

So, this PR makes the docs aside popover in wide window sizes
absolutely-positioned relative to the menu container, which removes all
flickering. On top of that, I'm adding a `DocumentationEdge` enum that
allows to control the edge anchor of the docs aside, which is useful in
this particular mode selector example to make the layout work well.


https://github.com/user-attachments/assets/a3e811e1-86b4-4839-a219-c3b0734532b3

When the window is small, the docs aside continue to be a sibling flex
container, which causes a super subtle shift in the items within the
menu popover. This is something I want to pursue fixing, but didn't want
to delay this PR too much.

Release Notes:

- N/A
This commit is contained in:
Danilo Leal
2025-09-12 14:22:35 -03:00
committed by GitHub
parent 85f7bb6277
commit 2b3ca360c3
6 changed files with 79 additions and 54 deletions
+3 -3
View File
@@ -17,8 +17,8 @@ use project::{
};
use settings::{Settings as _, SettingsStore};
use ui::{
Context, ContextMenu, ContextMenuEntry, ContextMenuItem, DocumentationAside, DocumentationSide,
Indicator, PopoverMenu, PopoverMenuHandle, Tooltip, Window, prelude::*,
Context, ContextMenu, ContextMenuEntry, ContextMenuItem, DocumentationAside, DocumentationEdge,
DocumentationSide, Indicator, PopoverMenu, PopoverMenuHandle, Tooltip, Window, prelude::*,
};
use workspace::{StatusItemView, Workspace};
@@ -121,7 +121,6 @@ impl LanguageServerHealthStatus {
impl LanguageServerState {
fn fill_menu(&self, mut menu: ContextMenu, cx: &mut Context<Self>) -> ContextMenu {
menu = menu.align_popover_bottom();
let lsp_logs = cx
.try_global::<GlobalLogStore>()
.map(|lsp_logs| lsp_logs.0.clone());
@@ -357,6 +356,7 @@ impl LanguageServerState {
message.map(|server_message| {
DocumentationAside::new(
DocumentationSide::Right,
DocumentationEdge::Bottom,
Rc::new(move |_| Label::new(server_message.clone()).into_any_element()),
)
}),