Merge branch 'main' into zed2-breadcrumbs

This commit is contained in:
Julia 2023-12-01 11:02:34 -05:00
commit 13f4cc563c
58 changed files with 2606 additions and 3167 deletions

View file

@ -1,7 +1,7 @@
use gpui::AnyView;
use crate::prelude::*;
use crate::{ButtonCommon, ButtonLike, ButtonSize2, ButtonStyle2, Label, LineHeightStyle};
use crate::{ButtonCommon, ButtonLike, ButtonSize, ButtonStyle, Label, LineHeightStyle};
#[derive(IntoElement)]
pub struct Button {
@ -54,12 +54,12 @@ impl ButtonCommon for Button {
self.base.id()
}
fn style(mut self, style: ButtonStyle2) -> Self {
fn style(mut self, style: ButtonStyle) -> Self {
self.base = self.base.style(style);
self
}
fn size(mut self, size: ButtonSize2) -> Self {
fn size(mut self, size: ButtonSize) -> Self {
self.base = self.base.size(size);
self
}
@ -79,7 +79,7 @@ impl RenderOnce for Button {
} else if self.base.selected {
Color::Selected
} else {
Color::Default
self.label_color.unwrap_or_default()
};
self.base.child(

View file

@ -1,4 +1,4 @@
use gpui::{rems, AnyElement, AnyView, ClickEvent, Div, Hsla, Rems, Stateful};
use gpui::{rems, transparent_black, AnyElement, AnyView, ClickEvent, Div, Hsla, Rems, Stateful};
use smallvec::SmallVec;
use crate::h_stack;
@ -6,13 +6,13 @@ use crate::prelude::*;
pub trait ButtonCommon: Clickable + Disableable {
fn id(&self) -> &ElementId;
fn style(self, style: ButtonStyle2) -> Self;
fn size(self, size: ButtonSize2) -> Self;
fn style(self, style: ButtonStyle) -> Self;
fn size(self, size: ButtonSize) -> Self;
fn tooltip(self, tooltip: impl Fn(&mut WindowContext) -> AnyView + 'static) -> Self;
}
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Default)]
pub enum ButtonStyle2 {
pub enum ButtonStyle {
#[default]
Filled,
// Tinted,
@ -21,54 +21,57 @@ pub enum ButtonStyle2 {
}
#[derive(Debug, Clone)]
pub struct ButtonStyle {
pub(crate) struct ButtonLikeStyles {
pub background: Hsla,
#[allow(unused)]
pub border_color: Hsla,
#[allow(unused)]
pub label_color: Hsla,
#[allow(unused)]
pub icon_color: Hsla,
}
impl ButtonStyle2 {
pub fn enabled(self, cx: &mut WindowContext) -> ButtonStyle {
impl ButtonStyle {
pub(crate) fn enabled(self, cx: &mut WindowContext) -> ButtonLikeStyles {
match self {
ButtonStyle2::Filled => ButtonStyle {
ButtonStyle::Filled => ButtonLikeStyles {
background: cx.theme().colors().element_background,
border_color: gpui::transparent_black(),
border_color: transparent_black(),
label_color: Color::Default.color(cx),
icon_color: Color::Default.color(cx),
},
ButtonStyle2::Subtle => ButtonStyle {
ButtonStyle::Subtle => ButtonLikeStyles {
background: cx.theme().colors().ghost_element_background,
border_color: gpui::transparent_black(),
border_color: transparent_black(),
label_color: Color::Default.color(cx),
icon_color: Color::Default.color(cx),
},
ButtonStyle2::Transparent => ButtonStyle {
background: gpui::transparent_black(),
border_color: gpui::transparent_black(),
ButtonStyle::Transparent => ButtonLikeStyles {
background: transparent_black(),
border_color: transparent_black(),
label_color: Color::Default.color(cx),
icon_color: Color::Default.color(cx),
},
}
}
pub fn hovered(self, cx: &mut WindowContext) -> ButtonStyle {
pub(crate) fn hovered(self, cx: &mut WindowContext) -> ButtonLikeStyles {
match self {
ButtonStyle2::Filled => ButtonStyle {
ButtonStyle::Filled => ButtonLikeStyles {
background: cx.theme().colors().element_hover,
border_color: gpui::transparent_black(),
border_color: transparent_black(),
label_color: Color::Default.color(cx),
icon_color: Color::Default.color(cx),
},
ButtonStyle2::Subtle => ButtonStyle {
ButtonStyle::Subtle => ButtonLikeStyles {
background: cx.theme().colors().ghost_element_hover,
border_color: gpui::transparent_black(),
border_color: transparent_black(),
label_color: Color::Default.color(cx),
icon_color: Color::Default.color(cx),
},
ButtonStyle2::Transparent => ButtonStyle {
background: gpui::transparent_black(),
border_color: gpui::transparent_black(),
ButtonStyle::Transparent => ButtonLikeStyles {
background: transparent_black(),
border_color: transparent_black(),
// TODO: These are not great
label_color: Color::Muted.color(cx),
// TODO: These are not great
@ -77,23 +80,23 @@ impl ButtonStyle2 {
}
}
pub fn active(self, cx: &mut WindowContext) -> ButtonStyle {
pub(crate) fn active(self, cx: &mut WindowContext) -> ButtonLikeStyles {
match self {
ButtonStyle2::Filled => ButtonStyle {
ButtonStyle::Filled => ButtonLikeStyles {
background: cx.theme().colors().element_active,
border_color: gpui::transparent_black(),
border_color: transparent_black(),
label_color: Color::Default.color(cx),
icon_color: Color::Default.color(cx),
},
ButtonStyle2::Subtle => ButtonStyle {
ButtonStyle::Subtle => ButtonLikeStyles {
background: cx.theme().colors().ghost_element_active,
border_color: gpui::transparent_black(),
border_color: transparent_black(),
label_color: Color::Default.color(cx),
icon_color: Color::Default.color(cx),
},
ButtonStyle2::Transparent => ButtonStyle {
background: gpui::transparent_black(),
border_color: gpui::transparent_black(),
ButtonStyle::Transparent => ButtonLikeStyles {
background: transparent_black(),
border_color: transparent_black(),
// TODO: These are not great
label_color: Color::Muted.color(cx),
// TODO: These are not great
@ -102,22 +105,23 @@ impl ButtonStyle2 {
}
}
pub fn focused(self, cx: &mut WindowContext) -> ButtonStyle {
#[allow(unused)]
pub(crate) fn focused(self, cx: &mut WindowContext) -> ButtonLikeStyles {
match self {
ButtonStyle2::Filled => ButtonStyle {
ButtonStyle::Filled => ButtonLikeStyles {
background: cx.theme().colors().element_background,
border_color: cx.theme().colors().border_focused,
label_color: Color::Default.color(cx),
icon_color: Color::Default.color(cx),
},
ButtonStyle2::Subtle => ButtonStyle {
ButtonStyle::Subtle => ButtonLikeStyles {
background: cx.theme().colors().ghost_element_background,
border_color: cx.theme().colors().border_focused,
label_color: Color::Default.color(cx),
icon_color: Color::Default.color(cx),
},
ButtonStyle2::Transparent => ButtonStyle {
background: gpui::transparent_black(),
ButtonStyle::Transparent => ButtonLikeStyles {
background: transparent_black(),
border_color: cx.theme().colors().border_focused,
label_color: Color::Accent.color(cx),
icon_color: Color::Accent.color(cx),
@ -125,23 +129,23 @@ impl ButtonStyle2 {
}
}
pub fn disabled(self, cx: &mut WindowContext) -> ButtonStyle {
pub(crate) fn disabled(self, cx: &mut WindowContext) -> ButtonLikeStyles {
match self {
ButtonStyle2::Filled => ButtonStyle {
ButtonStyle::Filled => ButtonLikeStyles {
background: cx.theme().colors().element_disabled,
border_color: cx.theme().colors().border_disabled,
label_color: Color::Disabled.color(cx),
icon_color: Color::Disabled.color(cx),
},
ButtonStyle2::Subtle => ButtonStyle {
ButtonStyle::Subtle => ButtonLikeStyles {
background: cx.theme().colors().ghost_element_disabled,
border_color: cx.theme().colors().border_disabled,
label_color: Color::Disabled.color(cx),
icon_color: Color::Disabled.color(cx),
},
ButtonStyle2::Transparent => ButtonStyle {
background: gpui::transparent_black(),
border_color: gpui::transparent_black(),
ButtonStyle::Transparent => ButtonLikeStyles {
background: transparent_black(),
border_color: transparent_black(),
label_color: Color::Disabled.color(cx),
icon_color: Color::Disabled.color(cx),
},
@ -150,19 +154,19 @@ impl ButtonStyle2 {
}
#[derive(Default, PartialEq, Clone, Copy)]
pub enum ButtonSize2 {
pub enum ButtonSize {
#[default]
Default,
Compact,
None,
}
impl ButtonSize2 {
impl ButtonSize {
fn height(self) -> Rems {
match self {
ButtonSize2::Default => rems(22. / 16.),
ButtonSize2::Compact => rems(18. / 16.),
ButtonSize2::None => rems(16. / 16.),
ButtonSize::Default => rems(22. / 16.),
ButtonSize::Compact => rems(18. / 16.),
ButtonSize::None => rems(16. / 16.),
}
}
}
@ -170,10 +174,10 @@ impl ButtonSize2 {
#[derive(IntoElement)]
pub struct ButtonLike {
id: ElementId,
pub(super) style: ButtonStyle2,
pub(super) style: ButtonStyle,
pub(super) disabled: bool,
pub(super) selected: bool,
size: ButtonSize2,
size: ButtonSize,
tooltip: Option<Box<dyn Fn(&mut WindowContext) -> AnyView>>,
on_click: Option<Box<dyn Fn(&ClickEvent, &mut WindowContext) + 'static>>,
children: SmallVec<[AnyElement; 2]>,
@ -183,10 +187,10 @@ impl ButtonLike {
pub fn new(id: impl Into<ElementId>) -> Self {
Self {
id: id.into(),
style: ButtonStyle2::default(),
style: ButtonStyle::default(),
disabled: false,
selected: false,
size: ButtonSize2::Default,
size: ButtonSize::Default,
tooltip: None,
children: SmallVec::new(),
on_click: None,
@ -220,12 +224,12 @@ impl ButtonCommon for ButtonLike {
&self.id
}
fn style(mut self, style: ButtonStyle2) -> Self {
fn style(mut self, style: ButtonStyle) -> Self {
self.style = style;
self
}
fn size(mut self, size: ButtonSize2) -> Self {
fn size(mut self, size: ButtonSize) -> Self {
self.size = size;
self
}

View file

@ -1,7 +1,7 @@
use gpui::{Action, AnyView};
use crate::prelude::*;
use crate::{ButtonCommon, ButtonLike, ButtonSize2, ButtonStyle2, Icon, IconElement, IconSize};
use crate::{ButtonCommon, ButtonLike, ButtonSize, ButtonStyle, Icon, IconElement, IconSize};
#[derive(IntoElement)]
pub struct IconButton {
@ -65,12 +65,12 @@ impl ButtonCommon for IconButton {
self.base.id()
}
fn style(mut self, style: ButtonStyle2) -> Self {
fn style(mut self, style: ButtonStyle) -> Self {
self.base = self.base.style(style);
self
}
fn size(mut self, size: ButtonSize2) -> Self {
fn size(mut self, size: ButtonSize) -> Self {
self.base = self.base.size(size);
self
}

View file

@ -1,73 +1,11 @@
mod list;
mod list_header;
mod list_item;
mod list_separator;
mod list_sub_header;
use gpui::{AnyElement, Div};
use smallvec::SmallVec;
use crate::prelude::*;
use crate::{v_stack, Label};
pub use list::*;
pub use list_header::*;
pub use list_item::*;
pub use list_separator::*;
pub use list_sub_header::*;
#[derive(IntoElement)]
pub struct List {
/// Message to display when the list is empty
/// Defaults to "No items"
empty_message: SharedString,
header: Option<ListHeader>,
toggle: Option<bool>,
children: SmallVec<[AnyElement; 2]>,
}
impl List {
pub fn new() -> Self {
Self {
empty_message: "No items".into(),
header: None,
toggle: None,
children: SmallVec::new(),
}
}
pub fn empty_message(mut self, empty_message: impl Into<SharedString>) -> Self {
self.empty_message = empty_message.into();
self
}
pub fn header(mut self, header: ListHeader) -> Self {
self.header = Some(header);
self
}
pub fn toggle(mut self, toggle: impl Into<Option<bool>>) -> Self {
self.toggle = toggle.into();
self
}
}
impl ParentElement for List {
fn children_mut(&mut self) -> &mut SmallVec<[AnyElement; 2]> {
&mut self.children
}
}
impl RenderOnce for List {
type Rendered = Div;
fn render(self, _cx: &mut WindowContext) -> Self::Rendered {
v_stack()
.w_full()
.py_1()
.children(self.header.map(|header| header))
.map(|this| match (self.children.is_empty(), self.toggle) {
(false, _) => this.children(self.children),
(true, Some(false)) => this,
(true, _) => this.child(Label::new(self.empty_message.clone()).color(Color::Muted)),
})
}
}

View file

@ -0,0 +1,60 @@
use gpui::{AnyElement, Div};
use smallvec::SmallVec;
use crate::{prelude::*, v_stack, Label, ListHeader};
#[derive(IntoElement)]
pub struct List {
/// Message to display when the list is empty
/// Defaults to "No items"
empty_message: SharedString,
header: Option<ListHeader>,
toggle: Option<bool>,
children: SmallVec<[AnyElement; 2]>,
}
impl List {
pub fn new() -> Self {
Self {
empty_message: "No items".into(),
header: None,
toggle: None,
children: SmallVec::new(),
}
}
pub fn empty_message(mut self, empty_message: impl Into<SharedString>) -> Self {
self.empty_message = empty_message.into();
self
}
pub fn header(mut self, header: impl Into<Option<ListHeader>>) -> Self {
self.header = header.into();
self
}
pub fn toggle(mut self, toggle: impl Into<Option<bool>>) -> Self {
self.toggle = toggle.into();
self
}
}
impl ParentElement for List {
fn children_mut(&mut self) -> &mut SmallVec<[AnyElement; 2]> {
&mut self.children
}
}
impl RenderOnce for List {
type Rendered = Div;
fn render(self, _cx: &mut WindowContext) -> Self::Rendered {
v_stack().w_full().py_1().children(self.header).map(|this| {
match (self.children.is_empty(), self.toggle) {
(false, _) => this.children(self.children),
(true, Some(false)) => this,
(true, _) => this.child(Label::new(self.empty_message.clone()).color(Color::Muted)),
}
})
}
}

View file

@ -1,22 +1,16 @@
use std::rc::Rc;
use gpui::{ClickEvent, Div};
use gpui::{AnyElement, ClickEvent, Div};
use smallvec::SmallVec;
use crate::prelude::*;
use crate::{h_stack, Disclosure, Icon, IconButton, IconElement, IconSize, Label};
pub enum ListHeaderMeta {
Tools(Vec<IconButton>),
// TODO: This should be a button
Button(Label),
Text(Label),
}
use crate::{h_stack, Disclosure, Icon, IconElement, IconSize, Label};
#[derive(IntoElement)]
pub struct ListHeader {
label: SharedString,
left_icon: Option<Icon>,
meta: Option<ListHeaderMeta>,
meta: SmallVec<[AnyElement; 2]>,
toggle: Option<bool>,
on_toggle: Option<Rc<dyn Fn(&ClickEvent, &mut WindowContext) + 'static>>,
inset: bool,
@ -28,7 +22,7 @@ impl ListHeader {
Self {
label: label.into(),
left_icon: None,
meta: None,
meta: SmallVec::new(),
inset: false,
toggle: None,
on_toggle: None,
@ -49,21 +43,19 @@ impl ListHeader {
self
}
pub fn left_icon(mut self, left_icon: Option<Icon>) -> Self {
self.left_icon = left_icon;
pub fn left_icon(mut self, left_icon: impl Into<Option<Icon>>) -> Self {
self.left_icon = left_icon.into();
self
}
pub fn right_button(self, button: IconButton) -> Self {
self.meta(Some(ListHeaderMeta::Tools(vec![button])))
}
pub fn meta(mut self, meta: Option<ListHeaderMeta>) -> Self {
self.meta = meta;
pub fn meta(mut self, meta: impl IntoElement) -> Self {
self.meta.push(meta.into_any_element());
self
}
}
pub fn selected(mut self, selected: bool) -> Self {
impl Selectable for ListHeader {
fn selected(mut self, selected: bool) -> Self {
self.selected = selected;
self
}
@ -73,18 +65,6 @@ impl RenderOnce for ListHeader {
type Rendered = Div;
fn render(self, cx: &mut WindowContext) -> Self::Rendered {
let meta = match self.meta {
Some(ListHeaderMeta::Tools(icons)) => div().child(
h_stack()
.gap_2()
.items_center()
.children(icons.into_iter().map(|i| i.icon_color(Color::Muted))),
),
Some(ListHeaderMeta::Button(label)) => div().child(label),
Some(ListHeaderMeta::Text(label)) => div().child(label),
None => div(),
};
h_stack().w_full().relative().child(
div()
.h_5()
@ -118,7 +98,7 @@ impl RenderOnce for ListHeader {
.map(|is_open| Disclosure::new(is_open).on_toggle(self.on_toggle)),
),
)
.child(meta),
.child(h_stack().gap_2().items_center().children(self.meta)),
)
}
}

View file

@ -83,11 +83,6 @@ impl ListItem {
self
}
pub fn selected(mut self, selected: bool) -> Self {
self.selected = selected;
self
}
pub fn left_child(mut self, left_content: impl IntoElement) -> Self {
self.left_slot = Some(left_content.into_any_element());
self
@ -109,6 +104,13 @@ impl ListItem {
}
}
impl Selectable for ListItem {
fn selected(mut self, selected: bool) -> Self {
self.selected = selected;
self
}
}
impl ParentElement for ListItem {
fn children_mut(&mut self) -> &mut SmallVec<[AnyElement; 2]> {
&mut self.children

View file

@ -8,6 +8,7 @@ mod icon_button;
mod keybinding;
mod label;
mod list;
mod list_header;
mod list_item;
pub use avatar::*;
@ -20,4 +21,5 @@ pub use icon_button::*;
pub use keybinding::*;
pub use label::*;
pub use list::*;
pub use list_header::*;
pub use list_item::*;

View file

@ -2,7 +2,7 @@ use gpui::{Div, Render};
use story::Story;
use crate::prelude::*;
use crate::{Button, ButtonStyle2};
use crate::{Button, ButtonStyle};
pub struct ButtonStory;
@ -14,9 +14,13 @@ impl Render for ButtonStory {
.child(Story::title_for::<Button>())
.child(Story::label("Default"))
.child(Button::new("default_filled", "Click me"))
.child(Story::label("Selected"))
.child(Button::new("selected_filled", "Click me").selected(true))
.child(Story::label("With `label_color`"))
.child(Button::new("filled_with_label_color", "Click me").color(Color::Created))
.child(Story::label("Default (Subtle)"))
.child(Button::new("default_subtle", "Click me").style(ButtonStyle2::Subtle))
.child(Button::new("default_subtle", "Click me").style(ButtonStyle::Subtle))
.child(Story::label("Default (Transparent)"))
.child(Button::new("default_transparent", "Click me").style(ButtonStyle2::Transparent))
.child(Button::new("default_transparent", "Click me").style(ButtonStyle::Transparent))
}
}

View file

@ -22,12 +22,12 @@ impl Render for ListStory {
.child(Story::label("With sections"))
.child(
List::new()
.child(ListHeader::new("Fruits"))
.header(ListHeader::new("Produce"))
.child(ListSubHeader::new("Fruits"))
.child(ListItem::new("apple").child("Apple"))
.child(ListItem::new("banana").child("Banana"))
.child(ListItem::new("cherry").child("Cherry"))
.child(ListSeparator)
.child(ListHeader::new("Vegetables"))
.child(ListSubHeader::new("Root Vegetables"))
.child(ListItem::new("carrot").child("Carrot"))
.child(ListItem::new("potato").child("Potato"))

View file

@ -0,0 +1,33 @@
use gpui::{Div, Render};
use story::Story;
use crate::{prelude::*, IconButton};
use crate::{Icon, ListHeader};
pub struct ListHeaderStory;
impl Render for ListHeaderStory {
type Element = Div;
fn render(&mut self, _cx: &mut ViewContext<Self>) -> Self::Element {
Story::container()
.child(Story::title_for::<ListHeader>())
.child(Story::label("Default"))
.child(ListHeader::new("Section 1"))
.child(Story::label("With left icon"))
.child(ListHeader::new("Section 2").left_icon(Icon::Bell))
.child(Story::label("With left icon and meta"))
.child(
ListHeader::new("Section 3")
.left_icon(Icon::BellOff)
.meta(IconButton::new("action_1", Icon::Bolt)),
)
.child(Story::label("With multiple meta"))
.child(
ListHeader::new("Section 4")
.meta(IconButton::new("action_1", Icon::Bolt))
.meta(IconButton::new("action_2", Icon::ExclamationTriangle))
.meta(IconButton::new("action_3", Icon::Plus)),
)
}
}

View file

@ -1,12 +0,0 @@
use gpui::{ImageSource, SharedString};
use crate::Icon;
/// A slot utility that provides a way to to pass either
/// an icon or an image to a component.
#[derive(Debug, Clone)]
pub enum GraphicSlot {
Icon(Icon),
Avatar(ImageSource),
PublicActor(SharedString),
}

View file

@ -18,7 +18,6 @@ mod disableable;
mod fixed;
pub mod prelude;
mod selectable;
mod slot;
mod styled_ext;
mod styles;
pub mod utils;
@ -29,6 +28,5 @@ pub use disableable::*;
pub use fixed::*;
pub use prelude::*;
pub use selectable::*;
pub use slot::*;
pub use styled_ext::*;
pub use styles::*;