zeta: Revised data-collection onboarding experience (#24031)
Release Notes: - N/A --------- Co-authored-by: Danilo <danilo@zed.dev> Co-authored-by: Danilo Leal <daniloleal09@gmail.com> Co-authored-by: João Marcos <marcospb19@hotmail.com>
This commit is contained in:
parent
29e559d60c
commit
93f8ccaaee
31 changed files with 760 additions and 601 deletions
|
@ -385,6 +385,11 @@ impl ButtonLike {
|
|||
Self::new(id).rounding(ButtonLikeRounding::Right)
|
||||
}
|
||||
|
||||
pub fn opacity(mut self, opacity: f32) -> Self {
|
||||
self.base = self.base.opacity(opacity);
|
||||
self
|
||||
}
|
||||
|
||||
pub(crate) fn height(mut self, height: DefiniteLength) -> Self {
|
||||
self.height = Some(height);
|
||||
self
|
||||
|
|
|
@ -57,12 +57,19 @@ impl<M> Default for PopoverMenuHandle<M> {
|
|||
struct PopoverMenuHandleState<M> {
|
||||
menu_builder: Rc<dyn Fn(&mut Window, &mut App) -> Option<Entity<M>>>,
|
||||
menu: Rc<RefCell<Option<Entity<M>>>>,
|
||||
on_open: Option<Rc<dyn Fn(&mut Window, &mut App)>>,
|
||||
}
|
||||
|
||||
impl<M: ManagedView> PopoverMenuHandle<M> {
|
||||
pub fn show(&self, window: &mut Window, cx: &mut App) {
|
||||
if let Some(state) = self.0.borrow().as_ref() {
|
||||
show_menu(&state.menu_builder, &state.menu, window, cx);
|
||||
show_menu(
|
||||
&state.menu_builder,
|
||||
&state.menu,
|
||||
state.on_open.clone(),
|
||||
window,
|
||||
cx,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -118,6 +125,7 @@ pub struct PopoverMenu<M: ManagedView> {
|
|||
attach: Option<Corner>,
|
||||
offset: Option<Point<Pixels>>,
|
||||
trigger_handle: Option<PopoverMenuHandle<M>>,
|
||||
on_open: Option<Rc<dyn Fn(&mut Window, &mut App)>>,
|
||||
full_width: bool,
|
||||
}
|
||||
|
||||
|
@ -132,6 +140,7 @@ impl<M: ManagedView> PopoverMenu<M> {
|
|||
attach: None,
|
||||
offset: None,
|
||||
trigger_handle: None,
|
||||
on_open: None,
|
||||
full_width: false,
|
||||
}
|
||||
}
|
||||
|
@ -155,11 +164,14 @@ impl<M: ManagedView> PopoverMenu<M> {
|
|||
}
|
||||
|
||||
pub fn trigger<T: PopoverTrigger>(mut self, t: T) -> Self {
|
||||
self.child_builder = Some(Box::new(|menu, builder| {
|
||||
let on_open = self.on_open.clone();
|
||||
self.child_builder = Some(Box::new(move |menu, builder| {
|
||||
let open = menu.borrow().is_some();
|
||||
t.toggle_state(open)
|
||||
.when_some(builder, |el, builder| {
|
||||
el.on_click(move |_event, window, cx| show_menu(&builder, &menu, window, cx))
|
||||
el.on_click(move |_event, window, cx| {
|
||||
show_menu(&builder, &menu, on_open.clone(), window, cx)
|
||||
})
|
||||
})
|
||||
.into_any_element()
|
||||
}));
|
||||
|
@ -185,6 +197,12 @@ impl<M: ManagedView> PopoverMenu<M> {
|
|||
self
|
||||
}
|
||||
|
||||
/// attach something upon opening the menu
|
||||
pub fn on_open(mut self, on_open: Rc<dyn Fn(&mut Window, &mut App)>) -> Self {
|
||||
self.on_open = Some(on_open);
|
||||
self
|
||||
}
|
||||
|
||||
fn resolved_attach(&self) -> Corner {
|
||||
self.attach.unwrap_or(match self.anchor {
|
||||
Corner::TopLeft => Corner::BottomLeft,
|
||||
|
@ -209,6 +227,7 @@ impl<M: ManagedView> PopoverMenu<M> {
|
|||
fn show_menu<M: ManagedView>(
|
||||
builder: &Rc<dyn Fn(&mut Window, &mut App) -> Option<Entity<M>>>,
|
||||
menu: &Rc<RefCell<Option<Entity<M>>>>,
|
||||
on_open: Option<Rc<dyn Fn(&mut Window, &mut App)>>,
|
||||
window: &mut Window,
|
||||
cx: &mut App,
|
||||
) {
|
||||
|
@ -232,6 +251,10 @@ fn show_menu<M: ManagedView>(
|
|||
window.focus(&new_menu.focus_handle(cx));
|
||||
*menu.borrow_mut() = Some(new_menu);
|
||||
window.refresh();
|
||||
|
||||
if let Some(on_open) = on_open {
|
||||
on_open(window, cx);
|
||||
}
|
||||
}
|
||||
|
||||
pub struct PopoverMenuElementState<M> {
|
||||
|
@ -311,6 +334,7 @@ impl<M: ManagedView> Element for PopoverMenu<M> {
|
|||
*trigger_handle.0.borrow_mut() = Some(PopoverMenuHandleState {
|
||||
menu_builder,
|
||||
menu: element_state.menu.clone(),
|
||||
on_open: self.on_open.clone(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
use gpui::{div, hsla, prelude::*, AnyView, ElementId, Hsla, IntoElement, Styled, Window};
|
||||
use gpui::{
|
||||
div, hsla, prelude::*, AnyView, CursorStyle, ElementId, Hsla, IntoElement, Styled, Window,
|
||||
};
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::utils::is_light;
|
||||
|
@ -45,6 +47,7 @@ pub struct Checkbox {
|
|||
filled: bool,
|
||||
style: ToggleStyle,
|
||||
tooltip: Option<Box<dyn Fn(&mut Window, &mut App) -> AnyView>>,
|
||||
label: Option<SharedString>,
|
||||
}
|
||||
|
||||
impl Checkbox {
|
||||
|
@ -58,6 +61,7 @@ impl Checkbox {
|
|||
filled: false,
|
||||
style: ToggleStyle::default(),
|
||||
tooltip: None,
|
||||
label: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -99,6 +103,12 @@ impl Checkbox {
|
|||
self.tooltip = Some(Box::new(tooltip));
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the label for the checkbox.
|
||||
pub fn label(mut self, label: impl Into<SharedString>) -> Self {
|
||||
self.label = Some(label.into());
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl Checkbox {
|
||||
|
@ -116,11 +126,11 @@ impl Checkbox {
|
|||
|
||||
fn border_color(&self, cx: &App) -> Hsla {
|
||||
if self.disabled {
|
||||
return cx.theme().colors().border_disabled;
|
||||
return cx.theme().colors().border_variant;
|
||||
}
|
||||
|
||||
match self.style.clone() {
|
||||
ToggleStyle::Ghost => cx.theme().colors().border_variant,
|
||||
ToggleStyle::Ghost => cx.theme().colors().border,
|
||||
ToggleStyle::ElevationBased(elevation) => elevation.on_elevation_bg(cx),
|
||||
ToggleStyle::Custom(color) => color.opacity(0.3),
|
||||
}
|
||||
|
@ -153,10 +163,8 @@ impl RenderOnce for Checkbox {
|
|||
let bg_color = self.bg_color(cx);
|
||||
let border_color = self.border_color(cx);
|
||||
|
||||
h_flex()
|
||||
.id(self.id)
|
||||
let checkbox = h_flex()
|
||||
.justify_center()
|
||||
.items_center()
|
||||
.size(DynamicSpacing::Base20.rems(cx))
|
||||
.group(group_id.clone())
|
||||
.child(
|
||||
|
@ -171,13 +179,24 @@ impl RenderOnce for Checkbox {
|
|||
.bg(bg_color)
|
||||
.border_1()
|
||||
.border_color(border_color)
|
||||
.when(self.disabled, |this| {
|
||||
this.cursor(CursorStyle::OperationNotAllowed)
|
||||
})
|
||||
.when(self.disabled, |this| {
|
||||
this.bg(cx.theme().colors().element_disabled.opacity(0.6))
|
||||
})
|
||||
.when(!self.disabled, |this| {
|
||||
this.group_hover(group_id.clone(), |el| {
|
||||
el.bg(cx.theme().colors().element_hover)
|
||||
})
|
||||
})
|
||||
.children(icon),
|
||||
)
|
||||
);
|
||||
|
||||
h_flex()
|
||||
.id(self.id)
|
||||
.gap(DynamicSpacing::Base06.rems(cx))
|
||||
.child(checkbox)
|
||||
.when_some(
|
||||
self.on_click.filter(|_| !self.disabled),
|
||||
|this, on_click| {
|
||||
|
@ -186,6 +205,11 @@ impl RenderOnce for Checkbox {
|
|||
})
|
||||
},
|
||||
)
|
||||
// TODO: Allow label size to be different from default.
|
||||
// TODO: Allow label color to be different from muted.
|
||||
.when_some(self.label, |this, label| {
|
||||
this.child(Label::new(label).color(Color::Muted))
|
||||
})
|
||||
.when_some(self.tooltip, |this, tooltip| {
|
||||
this.tooltip(move |window, cx| tooltip(window, cx))
|
||||
})
|
||||
|
@ -203,6 +227,7 @@ pub struct CheckboxWithLabel {
|
|||
style: ToggleStyle,
|
||||
}
|
||||
|
||||
// TODO: Remove `CheckboxWithLabel` now that `label` is a method of `Checkbox`.
|
||||
impl CheckboxWithLabel {
|
||||
/// Creates a checkbox with an attached label.
|
||||
pub fn new(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue