Detailed changes
@@ -5,6 +5,13 @@ pub enum ButtonVariant {
Filled,
}
+#[derive(Default, PartialEq)]
+pub enum InputVariant {
+ #[default]
+ Ghost,
+ Filled,
+}
+
#[derive(Default, PartialEq, Clone, Copy)]
pub enum Shape {
#[default]
@@ -7,6 +7,7 @@ pub use component::follow_group::*;
pub use component::tab::*;
pub use module::chat_panel::*;
+pub use module::project_panel::*;
pub use module::status_bar::*;
pub use module::tab_bar::*;
pub use module::title_bar::*;
@@ -14,5 +15,7 @@ pub use module::title_bar::*;
pub use element::avatar::*;
pub use element::icon_button::*;
pub use element::indicator::*;
+pub use element::input::*;
+pub use element::label::*;
pub use element::text_button::*;
pub use element::tool_divider::*;
@@ -1,5 +1,7 @@
pub(crate) mod avatar;
pub(crate) mod icon_button;
pub(crate) mod indicator;
+pub(crate) mod input;
+pub(crate) mod label;
pub(crate) mod text_button;
pub(crate) mod tool_divider;
@@ -0,0 +1,99 @@
+use crate::prelude::{InputVariant, InteractionState};
+use crate::theme::theme;
+use gpui2::style::{StyleHelpers, Styleable};
+use gpui2::{elements::div, IntoElement};
+use gpui2::{Element, ParentElement, ViewContext};
+
+#[derive(Element)]
+pub struct Input {
+ placeholder: &'static str,
+ value: String,
+ state: InteractionState,
+ variant: InputVariant,
+}
+
+pub fn input(placeholder: &'static str) -> Input {
+ Input {
+ placeholder,
+ value: "".to_string(),
+ state: InteractionState::default(),
+ variant: InputVariant::default(),
+ }
+}
+
+impl Input {
+ pub fn value(mut self, value: String) -> Self {
+ self.value = value;
+ self
+ }
+ pub fn state(mut self, state: InteractionState) -> Self {
+ self.state = state;
+ self
+ }
+ pub fn variant(mut self, variant: InputVariant) -> Self {
+ self.variant = variant;
+ self
+ }
+
+ fn render<V: 'static>(&mut self, _: &mut V, cx: &mut ViewContext<V>) -> impl IntoElement<V> {
+ let theme = theme(cx);
+
+ let text_el;
+ let text_color;
+ let background_color_default;
+ let background_color_active;
+
+ let mut border_color_default = theme.middle.base.default.border;
+ let mut border_color_hover = theme.middle.base.hovered.border;
+ let mut border_color_active = theme.middle.base.pressed.border;
+ let border_color_focus = theme.middle.base.pressed.background;
+
+ match self.variant {
+ InputVariant::Ghost => {
+ background_color_default = theme.middle.base.default.background;
+ background_color_active = theme.middle.base.active.background;
+ }
+ InputVariant::Filled => {
+ background_color_default = theme.middle.on.default.background;
+ background_color_active = theme.middle.on.active.background;
+ }
+ };
+
+ if self.state == InteractionState::Focused {
+ border_color_default = theme.players[0].cursor;
+ border_color_hover = theme.players[0].cursor;
+ border_color_active = theme.players[0].cursor;
+ }
+
+ if self.state == InteractionState::Focused || self.state == InteractionState::Active {
+ text_el = self.value.clone();
+ text_color = theme.lowest.base.default.foreground;
+ } else {
+ text_el = self.placeholder.to_string().clone();
+ text_color = theme.lowest.base.disabled.foreground;
+ }
+
+ div()
+ .h_7()
+ .px_2()
+ .border()
+ .border_color(border_color_default)
+ .fill(background_color_default)
+ .hover()
+ .border_color(border_color_hover)
+ .active()
+ .border_color(border_color_active)
+ .fill(background_color_active)
+ .flex()
+ .items_center()
+ .child(
+ div()
+ .flex()
+ .items_center()
+ .text_sm()
+ .text_color(text_color)
+ .child(text_el)
+ .child(div().text_color(theme.players[0].cursor).child("|")),
+ )
+ }
+}
@@ -0,0 +1,49 @@
+use crate::theme::theme;
+use gpui2::elements::div;
+use gpui2::style::StyleHelpers;
+use gpui2::{Element, ViewContext};
+use gpui2::{IntoElement, ParentElement};
+
+#[derive(Default, PartialEq, Copy, Clone)]
+pub enum LabelColor {
+ #[default]
+ Default,
+ Created,
+ Modified,
+ Deleted,
+ Hidden,
+}
+
+#[derive(Element, Clone)]
+pub struct Label {
+ label: &'static str,
+ color: LabelColor,
+}
+
+pub fn label(label: &'static str) -> Label {
+ Label {
+ label: "Label",
+ color: LabelColor::Default,
+ }
+}
+
+impl Label {
+ pub fn color(mut self, color: LabelColor) -> Self {
+ self.color = color;
+ self
+ }
+
+ fn render<V: 'static>(&mut self, _: &mut V, cx: &mut ViewContext<V>) -> impl IntoElement<V> {
+ let theme = theme(cx);
+
+ let color = match self.color {
+ LabelColor::Default => theme.lowest.base.default.foreground,
+ LabelColor::Created => theme.lowest.positive.default.foreground,
+ LabelColor::Modified => theme.lowest.warning.default.foreground,
+ LabelColor::Deleted => theme.lowest.negative.default.foreground,
+ LabelColor::Hidden => theme.lowest.variant.default.foreground,
+ };
+
+ div().text_sm().text_color(color).child(self.label.clone())
+ }
+}
@@ -1,4 +1,5 @@
pub(crate) mod chat_panel;
+pub(crate) mod project_panel;
pub(crate) mod status_bar;
pub(crate) mod tab_bar;
pub(crate) mod title_bar;
@@ -0,0 +1,65 @@
+use crate::{
+ prelude::InteractionState,
+ theme::theme,
+ ui::{input, label, LabelColor},
+};
+use gpui2::{
+ elements::{div, div::ScrollState},
+ style::StyleHelpers,
+ ParentElement, ViewContext,
+};
+use gpui2::{Element, IntoElement};
+use std::marker::PhantomData;
+
+#[derive(Element)]
+pub struct ProjectPanel<V: 'static> {
+ view_type: PhantomData<V>,
+ scroll_state: ScrollState,
+}
+
+pub fn project_panel<V: 'static>(scroll_state: ScrollState) -> ProjectPanel<V> {
+ ProjectPanel {
+ view_type: PhantomData,
+ scroll_state,
+ }
+}
+
+impl<V: 'static> ProjectPanel<V> {
+ fn render(&mut self, _: &mut V, cx: &mut ViewContext<V>) -> impl IntoElement<V> {
+ let theme = theme(cx);
+
+ div()
+ .w_64()
+ .h_full()
+ .flex()
+ .flex_col()
+ .fill(theme.middle.base.default.background)
+ .child(
+ div()
+ .w_full()
+ .flex()
+ .flex_col()
+ .overflow_y_scroll(self.scroll_state.clone())
+ .child(
+ div().py_2().flex().flex_col().children(
+ std::iter::repeat_with(|| {
+ vec![
+ label("File"),
+ label("Modified File").color(LabelColor::Modified),
+ label("Created File").color(LabelColor::Created),
+ label("Deleted File").color(LabelColor::Deleted),
+ label("Hidden File").color(LabelColor::Hidden),
+ ]
+ })
+ .take(60)
+ .flatten(),
+ ),
+ ),
+ )
+ .child(
+ input("Find something...")
+ .value("buffe".to_string())
+ .state(InteractionState::Focused),
+ )
+ }
+}
@@ -1,7 +1,6 @@
use crate::{
- collab_panel::collab_panel,
theme::theme,
- ui::{chat_panel, status_bar, tab_bar, title_bar},
+ ui::{chat_panel, project_panel, status_bar, tab_bar, title_bar},
};
use gpui2::{
elements::{div, div::ScrollState},
@@ -42,7 +41,7 @@ impl WorkspaceElement {
.flex()
.flex_row()
.overflow_hidden()
- .child(collab_panel(self.left_scroll_state.clone()))
+ .child(project_panel(self.left_scroll_state.clone()))
.child(
div()
.h_full()