feat: Add Styled trait support to UI components

Added style support to Label, Panel, List, and Modal components by
implementing the gpui::Styled trait. This allows applying styles
directly to components without wrapping them in divs. Updated sidebar to
use Label component directly with styles instead of nested divs.
This commit is contained in:
Ignacio Perez
2025-12-26 12:37:32 -03:00
parent c4ab603176
commit 3c10f8fdb8
6 changed files with 59 additions and 22 deletions
+1 -4
View File
@@ -57,10 +57,7 @@ pub enum IconName {}
impl IconNamed for IconName { impl IconNamed for IconName {
fn path(&self) -> SharedString { fn path(&self) -> SharedString {
match self { match self {
// Mapear cada variante a su path SVG _ => todo!(),
// IconName::Check => "icons/check.svg".into(),
// IconName::Close => "icons/close.svg".into(),
_ => "".into(),
} }
} }
} }
+17 -9
View File
@@ -5,27 +5,35 @@ use crate::theme::ActiveTheme;
#[derive(gpui::IntoElement)] #[derive(gpui::IntoElement)]
pub struct Label { pub struct Label {
text: gpui::SharedString, text: gpui::SharedString,
style: gpui::StyleRefinement,
} }
impl Label { impl Label {
pub fn new(text: impl Into<gpui::SharedString>) -> Self { pub fn new(text: impl Into<gpui::SharedString>) -> Self {
Self { text: text.into() } Self {
text: text.into(),
style: gpui::StyleRefinement::default(),
}
} }
} }
// impl gpui::Styled for Label { impl gpui::Styled for Label {
// fn style(&mut self) -> &mut gpui::StyleRefinement { fn style(&mut self) -> &mut gpui::StyleRefinement {
// &mut self.style &mut self.style
// } }
// } }
impl RenderOnce for Label { impl RenderOnce for Label {
fn render(self, _window: &mut gpui::Window, cx: &mut gpui::App) -> impl gpui::IntoElement { fn render(mut self, _window: &mut gpui::Window, cx: &mut gpui::App) -> impl gpui::IntoElement {
let theme = cx.theme(); let theme = cx.theme();
gpui::div() let mut div = gpui::div()
.line_height(gpui::rems(1.25)) .line_height(gpui::rems(1.25))
.text_color(theme.foreground) .text_color(theme.foreground)
.child(gpui::StyledText::new(&self.text)) .child(gpui::StyledText::new(&self.text));
*div.style() = self.style;
div
} }
} }
+10
View File
@@ -29,6 +29,7 @@ pub struct List {
items: Vec<ListItem>, items: Vec<ListItem>,
selected_index: Option<usize>, selected_index: Option<usize>,
height: Option<gpui::Pixels>, height: Option<gpui::Pixels>,
style: gpui::StyleRefinement,
on_click: Option<Arc<dyn Fn(usize, &ListItem, &mut gpui::Context<Self>) + Send + Sync>>, on_click: Option<Arc<dyn Fn(usize, &ListItem, &mut gpui::Context<Self>) + Send + Sync>>,
on_hover: Option<Arc<dyn Fn(usize, bool, &ListItem, &mut gpui::Context<Self>) + Send + Sync>>, on_hover: Option<Arc<dyn Fn(usize, bool, &ListItem, &mut gpui::Context<Self>) + Send + Sync>>,
} }
@@ -40,6 +41,7 @@ impl List {
items: Vec::new(), items: Vec::new(),
selected_index: None, selected_index: None,
height: None, height: None,
style: gpui::StyleRefinement::default(),
on_click: None, on_click: None,
on_hover: None, on_hover: None,
} }
@@ -127,6 +129,12 @@ impl List {
} }
} }
impl gpui::Styled for List {
fn style(&mut self) -> &mut gpui::StyleRefinement {
&mut self.style
}
}
impl gpui::Render for List { impl gpui::Render for List {
fn render( fn render(
&mut self, &mut self,
@@ -193,6 +201,8 @@ impl gpui::Render for List {
container = container.h(height); container = container.h(height);
} }
*container.style() = self.style.clone();
container container
} }
} }
+8
View File
@@ -28,6 +28,7 @@ pub struct Modal {
open: bool, open: bool,
close_on_backdrop: bool, close_on_backdrop: bool,
last_action: Option<ModalAction>, last_action: Option<ModalAction>,
style: gpui::StyleRefinement,
on_close: Option<Arc<dyn Fn(ModalAction, &mut gpui::Context<Self>) + Send + Sync>>, on_close: Option<Arc<dyn Fn(ModalAction, &mut gpui::Context<Self>) + Send + Sync>>,
on_save: Option<Arc<dyn Fn(&mut gpui::Context<Self>) + Send + Sync>>, on_save: Option<Arc<dyn Fn(&mut gpui::Context<Self>) + Send + Sync>>,
on_cancel: Option<Arc<dyn Fn(&mut gpui::Context<Self>) + Send + Sync>>, on_cancel: Option<Arc<dyn Fn(&mut gpui::Context<Self>) + Send + Sync>>,
@@ -45,6 +46,7 @@ impl Modal {
open: false, open: false,
close_on_backdrop: true, close_on_backdrop: true,
last_action: None, last_action: None,
style: gpui::StyleRefinement::default(),
on_close: None, on_close: None,
on_save: None, on_save: None,
on_cancel: None, on_cancel: None,
@@ -222,6 +224,12 @@ impl Modal {
} }
} }
impl gpui::Styled for Modal {
fn style(&mut self) -> &mut gpui::StyleRefinement {
&mut self.style
}
}
impl gpui::Render for Modal { impl gpui::Render for Modal {
fn render( fn render(
&mut self, &mut self,
+14 -2
View File
@@ -8,6 +8,7 @@ pub struct Panel {
title: Option<String>, title: Option<String>,
border: f32, border: f32,
padding: f32, padding: f32,
style: gpui::StyleRefinement,
} }
impl Panel { impl Panel {
@@ -17,6 +18,7 @@ impl Panel {
title: None, title: None,
border: 1.0, border: 1.0,
padding: 8.0, padding: 8.0,
style: gpui::StyleRefinement::default(),
} }
} }
@@ -50,6 +52,12 @@ impl Panel {
} }
} }
impl gpui::Styled for Panel {
fn style(&mut self) -> &mut gpui::StyleRefinement {
&mut self.style
}
}
impl gpui::RenderOnce for Panel { impl gpui::RenderOnce for Panel {
fn render(mut self, _window: &mut gpui::Window, cx: &mut gpui::App) -> impl IntoElement { fn render(mut self, _window: &mut gpui::Window, cx: &mut gpui::App) -> impl IntoElement {
let theme = cx.theme(); let theme = cx.theme();
@@ -81,7 +89,7 @@ impl gpui::RenderOnce for Panel {
}) })
.collect(); .collect();
gpui::div() let mut div = gpui::div()
.size_full() .size_full()
.bg(theme.panel) .bg(theme.panel)
.border(gpui::px(self.border)) .border(gpui::px(self.border))
@@ -92,6 +100,10 @@ impl gpui::RenderOnce for Panel {
.flex_col() .flex_col()
.h_full() .h_full()
.children(header) .children(header)
.children(children) .children(children);
*div.style() = self.style;
div
} }
} }
+9 -7
View File
@@ -1,4 +1,8 @@
use crate::components::{divider::Divider, panel::Panel}; use crate::components::{
icon::{Icon, IconName, IconSize},
label::Label,
panel::Panel,
};
use crate::models::{FilterState, ProjectTree}; use crate::models::{FilterState, ProjectTree};
use crate::theme::ActiveTheme; use crate::theme::ActiveTheme;
use gpui::{Context, Div, Entity, IntoElement, Window, div, prelude::*, px}; use gpui::{Context, Div, Entity, IntoElement, Window, div, prelude::*, px};
@@ -299,11 +303,10 @@ impl Render for Sidebar {
.border_b_1() .border_b_1()
.border_color(theme.border) .border_color(theme.border)
.child( .child(
div() Label::new("PROJECTS")
.text_sm() .text_sm()
.font_weight(gpui::FontWeight::BOLD) .font_weight(gpui::FontWeight::BOLD)
.text_color(theme.foreground) .text_color(theme.foreground),
.child("PROJECTS"),
), ),
) )
.child( .child(
@@ -337,11 +340,10 @@ impl Render for Sidebar {
.border_b_1() .border_b_1()
.border_color(theme.border) .border_color(theme.border)
.child( .child(
div() Label::new("TAGS")
.text_sm() .text_sm()
.font_weight(gpui::FontWeight::BOLD) .font_weight(gpui::FontWeight::BOLD)
.text_color(theme.foreground) .text_color(theme.foreground),
.child("TAGS"),
), ),
) )
.child( .child(