@@ -2204,14 +2204,9 @@ impl CollabPanel {
.into_any_element()
}),
Section::Contacts => Some(
- div()
- .border_1()
- .border_color(gpui::red())
- .child(
- IconButton::new("add-contact", Icon::Plus)
- .on_click(cx.listener(|this, _, cx| this.toggle_contact_finder(cx)))
- .tooltip(|cx| Tooltip::text("Search for new contact", cx)),
- )
+ IconButton::new("add-contact", Icon::Plus)
+ .on_click(cx.listener(|this, _, cx| this.toggle_contact_finder(cx)))
+ .tooltip(|cx| Tooltip::text("Search for new contact", cx))
.into_any_element(),
),
Section::Channels => Some(
@@ -7,7 +7,7 @@ use gpui::{
use picker::{Picker, PickerDelegate};
use std::sync::Arc;
use theme::ActiveTheme as _;
-use ui::{prelude::*, Avatar};
+use ui::{prelude::*, Avatar, ListItem};
use util::{ResultExt as _, TryFutureExt};
use workspace::ModalView;
@@ -23,7 +23,7 @@ impl ContactFinder {
potential_contacts: Arc::from([]),
selected_index: 0,
};
- let picker = cx.build_view(|cx| Picker::new(delegate, cx));
+ let picker = cx.build_view(|cx| Picker::new(delegate, cx).modal(false));
Self { picker }
}
@@ -37,16 +37,17 @@ impl ContactFinder {
impl Render for ContactFinder {
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
- fn render_mode_button(text: &'static str) -> AnyElement {
- Label::new(text).into_any_element()
- }
-
v_stack()
+ .elevation_3(cx)
.child(
v_stack()
+ .px_2()
+ .py_1()
+ .bg(cx.theme().colors().element_background)
+ // HACK: Prevent the background color from overflowing the parent container.
+ .rounded_t(px(8.))
.child(Label::new("Contacts"))
- .child(h_stack().children([render_mode_button("Invite new contacts")]))
- .bg(cx.theme().colors().element_background),
+ .child(h_stack().child(Label::new("Invite new contacts"))),
)
.child(self.picker.clone())
.w(rems(34.))
@@ -72,7 +73,8 @@ impl FocusableView for ContactFinder {
}
impl PickerDelegate for ContactFinderDelegate {
- type ListItem = Div;
+ type ListItem = ListItem;
+
fn match_count(&self) -> usize {
self.potential_contacts.len()
}
@@ -150,46 +152,14 @@ impl PickerDelegate for ContactFinderDelegate {
ContactRequestStatus::RequestAccepted => None,
};
Some(
- div()
- .flex_1()
- .justify_between()
- .child(Avatar::new(user.avatar_uri.clone()))
+ ListItem::new(ix)
+ .inset(true)
+ .selected(selected)
+ .start_slot(Avatar::new(user.avatar_uri.clone()))
.child(Label::new(user.github_login.clone()))
- .children(icon_path.map(|icon_path| svg().path(icon_path))),
+ .end_slot::<IconElement>(
+ icon_path.map(|icon_path| IconElement::from_path(icon_path)),
+ ),
)
- // todo!()
- // Flex::row()
- // .with_children(user.avatar.clone().map(|avatar| {
- // Image::from_data(avatar)
- // .with_style(theme.contact_avatar)
- // .aligned()
- // .left()
- // }))
- // .with_child(
- // Label::new(user.github_login.clone(), style.label.clone())
- // .contained()
- // .with_style(theme.contact_username)
- // .aligned()
- // .left(),
- // )
- // .with_children(icon_path.map(|icon_path| {
- // Svg::new(icon_path)
- // .with_color(button_style.color)
- // .constrained()
- // .with_width(button_style.icon_width)
- // .aligned()
- // .contained()
- // .with_style(button_style.container)
- // .constrained()
- // .with_width(button_style.button_width)
- // .with_height(button_style.button_width)
- // .aligned()
- // .flex_float()
- // }))
- // .contained()
- // .with_style(style.container)
- // .constrained()
- // .with_height(tabbed_modal.row_height)
- // .into_any()
}
}
@@ -1,8 +1,8 @@
use editor::Editor;
use gpui::{
- div, prelude::*, rems, uniform_list, AnyElement, AppContext, DismissEvent, Div, EventEmitter,
- FocusHandle, FocusableView, Length, MouseButton, MouseDownEvent, Render, Task,
- UniformListScrollHandle, View, ViewContext, WindowContext,
+ div, prelude::*, rems, uniform_list, AppContext, DismissEvent, Div, EventEmitter, FocusHandle,
+ FocusableView, Length, MouseButton, MouseDownEvent, Render, Task, UniformListScrollHandle,
+ View, ViewContext, WindowContext,
};
use std::{cmp, sync::Arc};
use ui::{prelude::*, v_stack, Color, Divider, Label};
@@ -15,6 +15,11 @@ pub struct Picker<D: PickerDelegate> {
pending_update_matches: Option<Task<()>>,
confirm_on_update: Option<bool>,
width: Option<Length>,
+
+ /// Whether the `Picker` is rendered as a self-contained modal.
+ ///
+ /// Set this to `false` when rendering the `Picker` as part of a larger modal.
+ is_modal: bool,
}
pub trait PickerDelegate: Sized + 'static {
@@ -58,6 +63,7 @@ impl<D: PickerDelegate> Picker<D> {
pending_update_matches: None,
confirm_on_update: None,
width: None,
+ is_modal: true,
};
this.update_matches("".to_string(), cx);
this
@@ -68,6 +74,11 @@ impl<D: PickerDelegate> Picker<D> {
self
}
+ pub fn modal(mut self, modal: bool) -> Self {
+ self.is_modal = modal;
+ self
+ }
+
pub fn focus(&self, cx: &mut WindowContext) {
self.editor.update(cx, |editor, cx| editor.focus(cx));
}
@@ -234,7 +245,11 @@ impl<D: PickerDelegate> Render for Picker<D> {
el.w(width)
})
.overflow_hidden()
- .elevation_3(cx)
+ // This is a bit of a hack to remove the modal styling when we're rendering the `Picker`
+ // as a part of a modal rather than the entire modal.
+ //
+ // We should revisit how the `Picker` is styled to make it more composable.
+ .when(self.is_modal, |this| this.elevation_3(cx))
.on_action(cx.listener(Self::select_next))
.on_action(cx.listener(Self::select_prev))
.on_action(cx.listener(Self::select_first))
@@ -295,22 +310,3 @@ impl<D: PickerDelegate> Render for Picker<D> {
})
}
}
-
-pub fn simple_picker_match(
- selected: bool,
- cx: &mut WindowContext,
- children: impl FnOnce(&mut WindowContext) -> AnyElement,
-) -> AnyElement {
- let colors = cx.theme().colors();
-
- div()
- .px_1()
- .text_color(colors.text)
- .text_ui()
- .bg(colors.ghost_element_background)
- .rounded_md()
- .when(selected, |this| this.bg(colors.ghost_element_selected))
- .hover(|this| this.bg(colors.ghost_element_hover))
- .child((children)(cx))
- .into_any()
-}