popover: Fix click trigger to close popover. (#1559)
This commit is contained in:
parent
eef8abaa15
commit
3cd94ea0be
2 changed files with 55 additions and 11 deletions
|
|
@ -121,7 +121,10 @@ impl Popover {
|
|||
self
|
||||
}
|
||||
|
||||
/// Set the content of the popover.
|
||||
/// Set the content builder for content of the Popover.
|
||||
///
|
||||
/// This callback will called every time on render the popover.
|
||||
/// So, you should avoid creating new elements or entities in the content closure.
|
||||
pub fn content<F, E>(mut self, content: F) -> Self
|
||||
where
|
||||
E: IntoElement,
|
||||
|
|
@ -144,7 +147,8 @@ impl Popover {
|
|||
self
|
||||
}
|
||||
|
||||
/// Bind the focus handle to track focus inside the popover.
|
||||
/// Bind the focus handle to receive focus when the popover is opened.
|
||||
/// If you not set this, a new focus handle will be created for the popover to
|
||||
///
|
||||
/// If popover is opened, the focus will be moved to the focus handle.
|
||||
pub fn track_focus(mut self, handle: &FocusHandle) -> Self {
|
||||
|
|
@ -225,7 +229,16 @@ impl PopoverState {
|
|||
if self.open {
|
||||
let state = cx.entity();
|
||||
self.previous_focus = window.focused(cx);
|
||||
self.focus_handle(cx).focus(window);
|
||||
let focus_handle = if let Some(tracked_focus_handle) = self.tracked_focus_handle.clone()
|
||||
{
|
||||
tracked_focus_handle
|
||||
} else {
|
||||
self.focus_handle.clone()
|
||||
};
|
||||
|
||||
cx.defer_in(window, move |_, window, _| {
|
||||
focus_handle.focus(window);
|
||||
});
|
||||
|
||||
self._dismiss_subscription =
|
||||
Some(
|
||||
|
|
@ -246,9 +259,7 @@ impl PopoverState {
|
|||
if let Some(callback) = self.on_open_change.as_ref() {
|
||||
callback(&self.open, window, cx);
|
||||
}
|
||||
|
||||
cx.notify();
|
||||
window.refresh();
|
||||
}
|
||||
|
||||
fn on_action_cancel(&mut self, _: &Cancel, window: &mut Window, cx: &mut Context<Self>) {
|
||||
|
|
@ -258,11 +269,7 @@ impl PopoverState {
|
|||
|
||||
impl Focusable for PopoverState {
|
||||
fn focus_handle(&self, _: &App) -> FocusHandle {
|
||||
if let Some(tracked_focus_handle) = &self.tracked_focus_handle {
|
||||
tracked_focus_handle.clone()
|
||||
} else {
|
||||
self.focus_handle.clone()
|
||||
}
|
||||
self.focus_handle.clone()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -294,7 +301,7 @@ impl RenderOnce for Popover {
|
|||
});
|
||||
|
||||
let open = state.read(cx).open;
|
||||
let focus_handle = state.read(cx).focus_handle.clone();
|
||||
let focus_handle = state.focus_handle(cx);
|
||||
let trigger_bounds = state.read(cx).trigger_bounds;
|
||||
|
||||
let Some(trigger) = self.trigger else {
|
||||
|
|
@ -310,6 +317,9 @@ impl RenderOnce for Popover {
|
|||
let state = state.clone();
|
||||
move |_, window, cx| {
|
||||
state.update(cx, |state, cx| {
|
||||
// We force set open to false to toggle it correctly.
|
||||
// Because if the mouse down out will toggle open first.
|
||||
state.open = open;
|
||||
state.toggle_open(window, cx);
|
||||
});
|
||||
cx.notify(parent_view_id);
|
||||
|
|
|
|||
|
|
@ -59,6 +59,40 @@ Popover::new("form-popover")
|
|||
.child(view.clone())
|
||||
```
|
||||
|
||||
### Add content by `content` method
|
||||
|
||||
The `content` method allows you to create more complex popover content using a closure. This is useful when
|
||||
you need to build dynamic content or need access to the popover's context.
|
||||
|
||||
This method will let us to have `&mut PopoverState`, `&mut Window` and `&mut Context<PopoverState>` parameters in the
|
||||
closure is to allow you to interact with the popover's state and the overall application context if needed.
|
||||
|
||||
:::warning
|
||||
This `content` callback will called every time on render the popover.
|
||||
So, you should avoid creating new elements or entities in the content closure
|
||||
or other heavy operations that may impact performance.
|
||||
:::
|
||||
|
||||
And `content` will works with `child`, `children` methods together.
|
||||
|
||||
```rust
|
||||
use gpui::ParentElement as _;
|
||||
use gpui_component::popover::Popover;
|
||||
|
||||
Popover::new("complex-popover")
|
||||
.anchor(Corner::BottomLeft)
|
||||
.trigger(Button::new("complex").label("Complex Content").outline())
|
||||
.content(|_, _, _| {
|
||||
div()
|
||||
.child("This popover has complex content.")
|
||||
.child(
|
||||
Button::new("action-btn")
|
||||
.label("Perform Action")
|
||||
.outline()
|
||||
)
|
||||
})
|
||||
```
|
||||
|
||||
### Right-Click Popover
|
||||
|
||||
Sometimes you may want to show a popover on right-click, for example, to create a special your ownen context menu. The `mouse_button` method allows you to specify which mouse button triggers the popover.
|
||||
|
|
|
|||
Loading…
Reference in a new issue