Fix hover tooltips appearing after related element is pressed (#24540)

Closes https://github.com/zed-industries/zed/issues/23894

Reworks all trigger declarations from
`.trigger(element.tooltip(tooltip))` into
`.trigger_with_tooltip(element, tooltip)` , with new API disallowing
simultaneous trigger and tooltip display.

All existing `.trigger(` calls were replaced, except 2 not applicable
(in dock.rs and pane.rs), 15 left as ones without tooltips, and 2
unchanged places in `inline_completion_button.rs`, where


0f7bb2e9fd/crates/inline_completion_button/src/inline_completion_button.rs (L311-L319)

`with_animation` does not allow us to simply use the same approach.

Release Notes:

- Fixed hover tooltips appearing after related element is pressed

---------

Co-authored-by: Danilo Leal <daniloleal09@gmail.com>
This commit is contained in:
Kirill Bulatov 2025-02-10 02:16:12 +02:00 committed by GitHub
parent 1a133ab9d8
commit 6f7f0f30e2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
21 changed files with 218 additions and 180 deletions

View file

@ -2359,8 +2359,8 @@ impl ContextEditor {
.icon(IconName::Plus)
.icon_size(IconSize::Small)
.icon_color(Color::Muted)
.icon_position(IconPosition::Start)
.tooltip(Tooltip::text("Type / to insert via keyboard")),
.icon_position(IconPosition::Start),
Tooltip::text("Type / to insert via keyboard"),
)
}
@ -3323,10 +3323,10 @@ impl Render for ContextEditorToolbarItem {
.color(Color::Muted)
.size(IconSize::XSmall),
),
)
.tooltip(move |window, cx| {
Tooltip::for_action("Change Model", &ToggleModelSelector, window, cx)
}),
),
move |window, cx| {
Tooltip::for_action("Change Model", &ToggleModelSelector, window, cx)
},
)
.with_handle(self.language_model_selector_menu_handle.clone()),
)

View file

@ -1,17 +1,22 @@
use std::sync::Arc;
use assistant_slash_command::SlashCommandWorkingSet;
use gpui::{AnyElement, DismissEvent, SharedString, Task, WeakEntity};
use gpui::{AnyElement, AnyView, DismissEvent, SharedString, Task, WeakEntity};
use picker::{Picker, PickerDelegate, PickerEditorPosition};
use ui::{prelude::*, ListItem, ListItemSpacing, PopoverMenu, PopoverTrigger, Tooltip};
use crate::context_editor::ContextEditor;
#[derive(IntoElement)]
pub(super) struct SlashCommandSelector<T: PopoverTrigger> {
pub(super) struct SlashCommandSelector<T, TT>
where
T: PopoverTrigger + ButtonCommon,
TT: Fn(&mut Window, &mut App) -> AnyView + 'static,
{
working_set: Arc<SlashCommandWorkingSet>,
active_context_editor: WeakEntity<ContextEditor>,
trigger: T,
tooltip: TT,
}
#[derive(Clone)]
@ -48,16 +53,22 @@ pub(crate) struct SlashCommandDelegate {
selected_index: usize,
}
impl<T: PopoverTrigger> SlashCommandSelector<T> {
impl<T, TT> SlashCommandSelector<T, TT>
where
T: PopoverTrigger + ButtonCommon,
TT: Fn(&mut Window, &mut App) -> AnyView + 'static,
{
pub(crate) fn new(
working_set: Arc<SlashCommandWorkingSet>,
active_context_editor: WeakEntity<ContextEditor>,
trigger: T,
tooltip: TT,
) -> Self {
SlashCommandSelector {
working_set,
active_context_editor,
trigger,
tooltip,
}
}
}
@ -241,7 +252,11 @@ impl PickerDelegate for SlashCommandDelegate {
}
}
impl<T: PopoverTrigger> RenderOnce for SlashCommandSelector<T> {
impl<T, TT> RenderOnce for SlashCommandSelector<T, TT>
where
T: PopoverTrigger + ButtonCommon,
TT: Fn(&mut Window, &mut App) -> AnyView + 'static,
{
fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement {
let all_models = self
.working_set
@ -322,7 +337,7 @@ impl<T: PopoverTrigger> RenderOnce for SlashCommandSelector<T> {
.ok();
PopoverMenu::new("model-switcher")
.menu(move |_window, _cx| Some(picker_view.clone()))
.trigger(self.trigger)
.trigger_with_tooltip(self.trigger, self.tooltip)
.attach(gpui::Corner::TopLeft)
.anchor(gpui::Corner::BottomLeft)
.offset(gpui::Point {