Detailed changes
@@ -173,6 +173,7 @@ fn generate_custom_value_setter(
method
}
+/// Returns a vec of (Property name, has 'auto' suffix, tokens for accessing the property, documentation)
fn box_prefixes() -> Vec<(&'static str, bool, Vec<TokenStream2>, &'static str)> {
vec![
(
@@ -188,24 +189,32 @@ fn box_prefixes() -> Vec<(&'static str, bool, Vec<TokenStream2>, &'static str)>
vec![quote! {size.width}, quote! {size.height}],
"Sets the width and height of the element."
),
+ // TODO: These don't use the same size ramp as the others
+ // see https://tailwindcss.com/docs/max-width
(
"min_w",
true,
vec![quote! { min_size.width }],
"Sets the minimum width of the element. [Docs](https://tailwindcss.com/docs/min-width)",
),
+ // TODO: These don't use the same size ramp as the others
+ // see https://tailwindcss.com/docs/max-width
(
"min_h",
true,
vec![quote! { min_size.height }],
"Sets the minimum height of the element. [Docs](https://tailwindcss.com/docs/min-height)",
),
+ // TODO: These don't use the same size ramp as the others
+ // see https://tailwindcss.com/docs/max-width
(
"max_w",
true,
vec![quote! { max_size.width }],
"Sets the maximum width of the element. [Docs](https://tailwindcss.com/docs/max-width)",
),
+ // TODO: These don't use the same size ramp as the others
+ // see https://tailwindcss.com/docs/max-width
(
"max_h",
true,
@@ -336,6 +345,7 @@ fn box_prefixes() -> Vec<(&'static str, bool, Vec<TokenStream2>, &'static str)>
]
}
+/// Returns a vec of (Suffix size, tokens that correspond to this size, documentation)
fn box_suffixes() -> Vec<(&'static str, TokenStream2, &'static str)> {
vec![
("0", quote! { px(0.) }, "0px"),
@@ -65,6 +65,7 @@ pub enum ComponentStory {
ChatPanel,
CollabPanel,
CommandPalette,
+ Copilot,
ContextMenu,
Facepile,
Keybinding,
@@ -170,6 +171,10 @@ impl ComponentStory {
ui::TrafficLightsStory::new().into_any()
})
.into_any(),
+ Self::Copilot => view(cx.entity(|cx| ()), |_, _| {
+ ui::CopilotModalStory::new().into_any()
+ })
+ .into_any(),
Self::Workspace => ui::WorkspaceStory::view(cx).into_any(),
}
}
@@ -6,12 +6,14 @@ mod chat_panel;
mod collab_panel;
mod command_palette;
mod context_menu;
+mod copilot;
mod editor_pane;
mod facepile;
mod icon_button;
mod keybinding;
mod language_selector;
mod list;
+mod modal;
mod multi_buffer;
mod notification_toast;
mod notifications_panel;
@@ -40,12 +42,14 @@ pub use chat_panel::*;
pub use collab_panel::*;
pub use command_palette::*;
pub use context_menu::*;
+pub use copilot::*;
pub use editor_pane::*;
pub use facepile::*;
pub use icon_button::*;
pub use keybinding::*;
pub use language_selector::*;
pub use list::*;
+pub use modal::*;
pub use multi_buffer::*;
pub use notification_toast::*;
pub use notifications_panel::*;
@@ -0,0 +1,63 @@
+use std::marker::PhantomData;
+
+use crate::{prelude::*, Button, Label, LabelColor, Modal};
+
+#[derive(Element)]
+pub struct CopilotModal<S: 'static + Send + Sync + Clone> {
+ id: ElementId,
+ state_type: PhantomData<S>,
+}
+
+impl<S: 'static + Send + Sync + Clone> CopilotModal<S> {
+ pub fn new(id: impl Into<ElementId>) -> Self {
+ Self {
+ id: id.into(),
+ state_type: PhantomData,
+ }
+ }
+
+ fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
+ let color = ThemeColor::new(cx);
+
+ div().id(self.id.clone()).child(
+ Modal::new("some-id")
+ .title("Connect Copilot to Zed")
+ .child(Label::new("You can update your settings or sign out from the Copilot menu in the status bar.").color(LabelColor::Muted))
+ .primary_action(Button::new("Connect to Github").variant(ButtonVariant::Filled)),
+ )
+ }
+}
+
+#[cfg(feature = "stories")]
+pub use stories::*;
+
+#[cfg(feature = "stories")]
+mod stories {
+ use crate::Story;
+
+ use super::*;
+
+ #[derive(Element)]
+ pub struct CopilotModalStory<S: 'static + Send + Sync + Clone> {
+ state_type: PhantomData<S>,
+ }
+
+ impl<S: 'static + Send + Sync + Clone> CopilotModalStory<S> {
+ pub fn new() -> Self {
+ Self {
+ state_type: PhantomData,
+ }
+ }
+
+ fn render(
+ &mut self,
+ _view: &mut S,
+ cx: &mut ViewContext<S>,
+ ) -> impl Element<ViewState = S> {
+ Story::container(cx)
+ .child(Story::title_for::<_, CopilotModal<S>>(cx))
+ .child(Story::label(cx, "Default"))
+ .child(CopilotModal::new("copilot-modal"))
+ }
+ }
+}
@@ -518,13 +518,10 @@ impl<S: 'static + Send + Sync> ListDetailsEntry<S> {
this.child(Label::new(self.meta.clone().unwrap()).color(LabelColor::Muted))
})
.child(
- h_stack().gap_1().justify_end().children(
- self.actions
- .take()
- .unwrap_or_default()
- .into_iter()
- .map(|action| action),
- ),
+ h_stack()
+ .gap_1()
+ .justify_end()
+ .children(self.actions.take().unwrap_or_default().into_iter()),
)
}
}
@@ -0,0 +1,87 @@
+use std::marker::PhantomData;
+
+use gpui2::AnyElement;
+use smallvec::SmallVec;
+
+use crate::{h_stack, prelude::*, v_stack, Button, Icon, IconButton, Label};
+
+#[derive(Element)]
+pub struct Modal<S: 'static + Send + Sync> {
+ id: ElementId,
+ state_type: PhantomData<S>,
+ title: Option<SharedString>,
+ primary_action: Option<Button<S>>,
+ secondary_action: Option<Button<S>>,
+ children: SmallVec<[AnyElement<S>; 2]>,
+}
+
+impl<S: 'static + Send + Sync> Modal<S> {
+ pub fn new(id: impl Into<ElementId>) -> Self {
+ Self {
+ id: id.into(),
+ state_type: PhantomData,
+ title: None,
+ primary_action: None,
+ secondary_action: None,
+ children: SmallVec::new(),
+ }
+ }
+
+ pub fn title(mut self, title: impl Into<SharedString>) -> Self {
+ self.title = Some(title.into());
+ self
+ }
+
+ pub fn primary_action(mut self, action: Button<S>) -> Self {
+ self.primary_action = Some(action);
+ self
+ }
+
+ pub fn secondary_action(mut self, action: Button<S>) -> Self {
+ self.secondary_action = Some(action);
+ self
+ }
+
+ fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
+ let color = ThemeColor::new(cx);
+
+ v_stack()
+ .id(self.id.clone())
+ .w_96()
+ // .rounded_xl()
+ .bg(color.background)
+ .border()
+ .border_color(color.border)
+ .shadow_2xl()
+ .child(
+ h_stack()
+ .justify_between()
+ .p_1()
+ .border_b()
+ .border_color(color.border)
+ .child(div().children(self.title.clone().map(|t| Label::new(t))))
+ .child(IconButton::new(Icon::Close)),
+ )
+ .child(v_stack().p_1().children(self.children.drain(..)))
+ .when(
+ self.primary_action.is_some() || self.secondary_action.is_some(),
+ |this| {
+ this.child(
+ h_stack()
+ .border_t()
+ .border_color(color.border)
+ .p_1()
+ .justify_end()
+ .children(self.secondary_action.take())
+ .children(self.primary_action.take()),
+ )
+ },
+ )
+ }
+}
+
+impl<S: 'static + Send + Sync> ParentElement for Modal<S> {
+ fn children_mut(&mut self) -> &mut SmallVec<[AnyElement<Self::ViewState>; 2]> {
+ &mut self.children
+ }
+}
@@ -146,7 +146,11 @@ impl<S: 'static + Send + Sync> Button<S> {
self.icon.map(|i| IconElement::new(i).color(icon_color))
}
- fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
+ pub fn render(
+ &mut self,
+ _view: &mut S,
+ cx: &mut ViewContext<S>,
+ ) -> impl Element<ViewState = S> {
let icon_color = self.icon_color();
let border_color = self.border_color(cx);
let settings = user_settings(cx);
@@ -110,7 +110,7 @@ pub struct ThemeColor {
/// The background color of an elevated surface, like a modal, tooltip or toast.
pub elevated_surface: Hsla,
pub surface: Hsla,
- /// Window background color
+ /// Window background color of the base app
pub background: Hsla,
/// Default background for elements like filled buttons,
/// text fields, checkboxes, radio buttons, etc.
@@ -149,6 +149,7 @@ pub struct ThemeColor {
pub title_bar: Hsla,
pub toolbar: Hsla,
pub tab_bar: Hsla,
+ /// The background of the editor
pub editor: Hsla,
pub editor_subheader: Hsla,
pub editor_active_line: Hsla,