group_box: Update GroupBox style. (#1167)
- Removed padding x of the Group Title. - Added `fill` variant and change default to use no background and paddings style. <img width="1120" height="1337" alt="image" src="https://github.com/user-attachments/assets/958e902f-3481-424c-a923-62746175aabf" />
This commit is contained in:
parent
554082b969
commit
4e5aca3842
3 changed files with 114 additions and 36 deletions
|
|
@ -7,7 +7,9 @@ use gpui_component::{
|
||||||
button::{Button, ButtonVariants},
|
button::{Button, ButtonVariants},
|
||||||
checkbox::Checkbox,
|
checkbox::Checkbox,
|
||||||
group_box::GroupBox,
|
group_box::GroupBox,
|
||||||
|
h_flex,
|
||||||
radio::{Radio, RadioGroup},
|
radio::{Radio, RadioGroup},
|
||||||
|
switch::Switch,
|
||||||
text::TextView,
|
text::TextView,
|
||||||
v_flex, ActiveTheme as _, StyledExt,
|
v_flex, ActiveTheme as _, StyledExt,
|
||||||
};
|
};
|
||||||
|
|
@ -24,7 +26,8 @@ impl super::Story for GroupBoxStory {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn description() -> &'static str {
|
fn description() -> &'static str {
|
||||||
"A styled container element that with an optional title to groups related content together."
|
"A styled container element that with an optional title \
|
||||||
|
to groups related content together."
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_view(window: &mut Window, cx: &mut App) -> Entity<impl Render + Focusable> {
|
fn new_view(window: &mut Window, cx: &mut App) -> Entity<impl Render + Focusable> {
|
||||||
|
|
@ -58,21 +61,57 @@ impl Render for GroupBoxStory {
|
||||||
.justify_center()
|
.justify_center()
|
||||||
.gap_4()
|
.gap_4()
|
||||||
.child(
|
.child(
|
||||||
section("A simple GroupBox").w_128().child(
|
section("Default Style").w_128().child(
|
||||||
GroupBox::new()
|
GroupBox::new()
|
||||||
.title(Checkbox::new("all").label("Subscribe All"))
|
.child("Subscriptions")
|
||||||
|
.child(Checkbox::new("all").label("All"))
|
||||||
.child(Checkbox::new("news-letter").label("News Letter"))
|
.child(Checkbox::new("news-letter").label("News Letter"))
|
||||||
.child(Checkbox::new("account-activity").label("Account Activity"))
|
.child(Checkbox::new("account-activity").label("Account Activity"))
|
||||||
.child(Button::new("ok").primary().label("Send Mail")),
|
.child(Button::new("ok").primary().label("Update Subscriptions")),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.child(
|
.child(
|
||||||
section("Outline style").w_128().child(
|
section("Fill Style").w_128().child(
|
||||||
GroupBox::new().outline().title("Appearance").child(
|
GroupBox::new()
|
||||||
RadioGroup::vertical("theme")
|
.id("activity")
|
||||||
.child(Radio::new("light").label("Light"))
|
.fill()
|
||||||
.child(Radio::new("dark").label("Dark"))
|
.title("Contributions & activity")
|
||||||
.child(Radio::new("system").label("System")),
|
.child(
|
||||||
|
h_flex()
|
||||||
|
.justify_between()
|
||||||
|
.child("Make profile private and hide activity")
|
||||||
|
.child(Switch::new("toggle-0").checked(true)),
|
||||||
|
)
|
||||||
|
.child(
|
||||||
|
h_flex()
|
||||||
|
.justify_between()
|
||||||
|
.child("Include private contributions on my profile")
|
||||||
|
.child(Switch::new("toggle-1").checked(false)),
|
||||||
|
)
|
||||||
|
.child(Button::new("btn-1").primary().label("Save")),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.child(
|
||||||
|
section("Outline Style").w_128().child(
|
||||||
|
GroupBox::new()
|
||||||
|
.id("appearance")
|
||||||
|
.outline()
|
||||||
|
.title("Appearance")
|
||||||
|
.child(
|
||||||
|
RadioGroup::vertical("theme")
|
||||||
|
.child(Radio::new("light").label("Light"))
|
||||||
|
.child(Radio::new("dark").label("Dark"))
|
||||||
|
.child(Radio::new("system").label("System")),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.child(
|
||||||
|
section("Without Title").w_128().child(
|
||||||
|
GroupBox::new().outline().child(
|
||||||
|
h_flex()
|
||||||
|
.justify_between()
|
||||||
|
.child("Make profile private and hide activity")
|
||||||
|
.child(Switch::new("toggle-1").checked(true)),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
@ -84,16 +123,23 @@ impl Render for GroupBoxStory {
|
||||||
.rounded_xl()
|
.rounded_xl()
|
||||||
.p_5()
|
.p_5()
|
||||||
.title("This is a custom style")
|
.title("This is a custom style")
|
||||||
.title_style(StyleRefinement::default().font_semibold().line_height(relative(1.0)).px_3())
|
.title_style(
|
||||||
|
StyleRefinement::default()
|
||||||
|
.font_semibold()
|
||||||
|
.line_height(relative(1.0))
|
||||||
|
.px_3(),
|
||||||
|
)
|
||||||
.content_style(
|
.content_style(
|
||||||
StyleRefinement::default().rounded_xl()
|
StyleRefinement::default()
|
||||||
|
.rounded_xl()
|
||||||
.py_3()
|
.py_3()
|
||||||
.px_4()
|
.px_4()
|
||||||
.border_2()
|
.border_2(),
|
||||||
)
|
)
|
||||||
.child(TextView::markdown(
|
.child(TextView::markdown(
|
||||||
"custom-style",
|
"custom-style",
|
||||||
"You can use `title_style` to customize the style of the title. \n \
|
"You can use `title_style` to customize the style \
|
||||||
|
of the title. \n \
|
||||||
And any style in `GroupBox` will apply to the content container.",
|
And any style in `GroupBox` will apply to the content container.",
|
||||||
)),
|
)),
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -408,7 +408,6 @@ impl RenderOnce for StorySection {
|
||||||
.gap_4()
|
.gap_4()
|
||||||
.child(self.title),
|
.child(self.title),
|
||||||
)
|
)
|
||||||
.title_style(StyleRefinement::default().px_2())
|
|
||||||
.content_style(
|
.content_style(
|
||||||
StyleRefinement::default()
|
StyleRefinement::default()
|
||||||
.rounded_lg()
|
.rounded_lg()
|
||||||
|
|
|
||||||
|
|
@ -1,35 +1,71 @@
|
||||||
use gpui::{
|
use gpui::{
|
||||||
div, prelude::FluentBuilder, relative, AnyElement, App, IntoElement, ParentElement, RenderOnce,
|
div, prelude::FluentBuilder, relative, AnyElement, App, ElementId, InteractiveElement as _,
|
||||||
StyleRefinement, Styled, Window,
|
IntoElement, ParentElement, RenderOnce, StyleRefinement, Styled, Window,
|
||||||
};
|
};
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
|
|
||||||
use crate::{v_flex, ActiveTheme, StyledExt as _};
|
use crate::{v_flex, ActiveTheme, StyledExt as _};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Default, Copy, PartialEq, Eq, Hash)]
|
||||||
|
pub enum GroupBoxVariant {
|
||||||
|
#[default]
|
||||||
|
Normal,
|
||||||
|
Fill,
|
||||||
|
Outline,
|
||||||
|
}
|
||||||
|
|
||||||
/// GroupBox is a styled container element that with
|
/// GroupBox is a styled container element that with
|
||||||
/// an optional title to groups related content together.
|
/// an optional title to groups related content together.
|
||||||
#[derive(IntoElement)]
|
#[derive(IntoElement)]
|
||||||
pub struct GroupBox {
|
pub struct GroupBox {
|
||||||
|
id: Option<ElementId>,
|
||||||
|
variant: GroupBoxVariant,
|
||||||
style: StyleRefinement,
|
style: StyleRefinement,
|
||||||
title_style: StyleRefinement,
|
title_style: StyleRefinement,
|
||||||
title: Option<AnyElement>,
|
title: Option<AnyElement>,
|
||||||
content_style: StyleRefinement,
|
content_style: StyleRefinement,
|
||||||
outline: bool,
|
|
||||||
children: SmallVec<[AnyElement; 1]>,
|
children: SmallVec<[AnyElement; 1]>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GroupBox {
|
impl GroupBox {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
id: None,
|
||||||
|
variant: GroupBoxVariant::default(),
|
||||||
style: StyleRefinement::default(),
|
style: StyleRefinement::default(),
|
||||||
title_style: StyleRefinement::default(),
|
title_style: StyleRefinement::default(),
|
||||||
content_style: StyleRefinement::default(),
|
content_style: StyleRefinement::default(),
|
||||||
title: None,
|
title: None,
|
||||||
outline: false,
|
|
||||||
children: SmallVec::new(),
|
children: SmallVec::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set the variant of the group box.
|
||||||
|
pub fn variant(mut self, variant: GroupBoxVariant) -> Self {
|
||||||
|
self.variant = variant;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set to use Fill variant.
|
||||||
|
pub fn fill(mut self) -> Self {
|
||||||
|
self.variant = GroupBoxVariant::Fill;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set use outline style of the group box.
|
||||||
|
///
|
||||||
|
/// If true, the group box will have a border around it, and no background color.
|
||||||
|
pub fn outline(mut self) -> Self {
|
||||||
|
self.variant = GroupBoxVariant::Outline;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set the id of the group box, default is None.
|
||||||
|
pub fn id(mut self, id: impl Into<ElementId>) -> Self {
|
||||||
|
self.id = Some(id.into());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
/// Set the title of the group box, default is None.
|
/// Set the title of the group box, default is None.
|
||||||
pub fn title(mut self, title: impl IntoElement) -> Self {
|
pub fn title(mut self, title: impl IntoElement) -> Self {
|
||||||
self.title = Some(title.into_any_element());
|
self.title = Some(title.into_any_element());
|
||||||
|
|
@ -47,14 +83,6 @@ impl GroupBox {
|
||||||
self.content_style = style;
|
self.content_style = style;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set use outline style of the group box, default is false.
|
|
||||||
///
|
|
||||||
/// If true, the group box will have a border around it, and no background color.
|
|
||||||
pub fn outline(mut self) -> Self {
|
|
||||||
self.outline = true;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ParentElement for GroupBox {
|
impl ParentElement for GroupBox {
|
||||||
|
|
@ -71,15 +99,22 @@ impl Styled for GroupBox {
|
||||||
|
|
||||||
impl RenderOnce for GroupBox {
|
impl RenderOnce for GroupBox {
|
||||||
fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement {
|
fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement {
|
||||||
|
let (bg, border, has_paddings) = match self.variant {
|
||||||
|
GroupBoxVariant::Normal => (None, None, false),
|
||||||
|
GroupBoxVariant::Fill => (Some(cx.theme().group_box), None, true),
|
||||||
|
GroupBoxVariant::Outline => (None, Some(cx.theme().border), true),
|
||||||
|
};
|
||||||
|
|
||||||
v_flex()
|
v_flex()
|
||||||
|
.id(self.id.unwrap_or("group-box".into()))
|
||||||
.size_full()
|
.size_full()
|
||||||
.gap_2()
|
.when(has_paddings, |this| this.gap_3())
|
||||||
|
.when(!has_paddings, |this| this.gap_4())
|
||||||
.refine_style(&self.style)
|
.refine_style(&self.style)
|
||||||
.when_some(self.title, |this, title| {
|
.when_some(self.title, |this, title| {
|
||||||
this.child(
|
this.child(
|
||||||
div()
|
div()
|
||||||
.px_4()
|
.text_color(cx.theme().muted_foreground)
|
||||||
.text_color(cx.theme().group_box_foreground)
|
|
||||||
.line_height(relative(1.))
|
.line_height(relative(1.))
|
||||||
.refine_style(&self.title_style)
|
.refine_style(&self.title_style)
|
||||||
.child(title),
|
.child(title),
|
||||||
|
|
@ -87,13 +122,11 @@ impl RenderOnce for GroupBox {
|
||||||
})
|
})
|
||||||
.child(
|
.child(
|
||||||
v_flex()
|
v_flex()
|
||||||
.when(!self.outline, |this| this.bg(cx.theme().group_box))
|
.when_some(bg, |this, bg| this.bg(bg))
|
||||||
.when(self.outline, |this| {
|
.when_some(border, |this, border| this.border_color(border).border_1())
|
||||||
this.border_color(cx.theme().border).border_1()
|
|
||||||
})
|
|
||||||
.text_color(cx.theme().group_box_foreground)
|
.text_color(cx.theme().group_box_foreground)
|
||||||
.p_4()
|
.when(has_paddings, |this| this.p_4())
|
||||||
.gap_3()
|
.gap_4()
|
||||||
.rounded(cx.theme().radius)
|
.rounded(cx.theme().radius)
|
||||||
.refine_style(&self.content_style)
|
.refine_style(&self.content_style)
|
||||||
.children(self.children),
|
.children(self.children),
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue