checkbox: Add children to Radio, Checkbox to display long texts. (#724)
This change is going to solve the wrapped text line-height. Before this change, the Label is must set `line-height: 100%` to render at same line with the checkbox. But if there have a long text in label, wrapped lines need more line-height to leave lines spaces. But if we set line-height over the 100%, that the checkbox will not align horizontal center. So, this change to use other child to solve this issue, we can set line-height to the child not to the label. <img width="1204" alt="image" src="https://github.com/user-attachments/assets/981cf925-01c7-48d7-9dd2-881c727a1759" />
This commit is contained in:
parent
49e8b06ccb
commit
c98e4f0521
3 changed files with 80 additions and 34 deletions
|
|
@ -1,5 +1,5 @@
|
|||
use gpui::{
|
||||
px, App, AppContext, Context, Div, Entity, Focusable, IntoElement, ParentElement, Render,
|
||||
div, px, App, AppContext, Context, Div, Entity, Focusable, IntoElement, ParentElement, Render,
|
||||
SharedString, Styled, Window,
|
||||
};
|
||||
|
||||
|
|
@ -205,20 +205,27 @@ impl Render for SwitchStory {
|
|||
v.check3 = !v.check3;
|
||||
})),
|
||||
)
|
||||
.child(Checkbox::new("longlong-checkbox").w(px(300.)).label(
|
||||
"The long long label text, \
|
||||
it should wrap when the text is too long.",
|
||||
))
|
||||
.child(
|
||||
Checkbox::new("longlong-checkbox")
|
||||
.w(px(300.))
|
||||
.label("The long long label text.")
|
||||
.child(div().text_color(cx.theme().muted_foreground).child(
|
||||
"This is a long long label text that \
|
||||
should wrap when the text is too long.",
|
||||
)),
|
||||
)
|
||||
.child(
|
||||
Checkbox::new("longlong-markdown-checkbox")
|
||||
.w(px(300.))
|
||||
.label(
|
||||
.label("Label with description")
|
||||
.child(div().text_color(cx.theme().muted_foreground).child(
|
||||
TextView::markdown(
|
||||
"longlong-markdown-checkbox",
|
||||
"The [long long label](https://github.com) text used markdown, \
|
||||
it should wrap when the text is too long.",
|
||||
)
|
||||
),
|
||||
"The [long long label](https://github.com) \
|
||||
text used markdown, \
|
||||
it should wrap when the text is too long.",
|
||||
),
|
||||
)),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
|
@ -269,9 +276,11 @@ impl Render for SwitchStory {
|
|||
)
|
||||
.child(
|
||||
Radio::new("radio3")
|
||||
.label(
|
||||
"The long long label text, \
|
||||
it should wrap when the text is too long.",
|
||||
.label("The long long label text.")
|
||||
.child(
|
||||
div().text_color(cx.theme().muted_foreground).child(
|
||||
"This line should wrap when the text is too long.",
|
||||
),
|
||||
)
|
||||
.w(px(300.))
|
||||
.checked(true)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
use crate::{h_flex, text::Text, v_flex, ActiveTheme, Disableable, IconName, Selectable};
|
||||
use gpui::{
|
||||
div, prelude::FluentBuilder as _, px, relative, svg, App, Div, ElementId, InteractiveElement,
|
||||
IntoElement, ParentElement, RenderOnce, StatefulInteractiveElement as _, Styled, Window,
|
||||
div, prelude::FluentBuilder as _, px, relative, svg, AnyElement, App, Div, ElementId,
|
||||
InteractiveElement, IntoElement, ParentElement, RenderOnce, StatefulInteractiveElement as _,
|
||||
Styled, Window,
|
||||
};
|
||||
|
||||
/// A Checkbox element.
|
||||
|
|
@ -10,6 +11,7 @@ pub struct Checkbox {
|
|||
id: ElementId,
|
||||
base: Div,
|
||||
label: Option<Text>,
|
||||
children: Vec<AnyElement>,
|
||||
checked: bool,
|
||||
disabled: bool,
|
||||
on_click: Option<Box<dyn Fn(&bool, &mut Window, &mut App) + 'static>>,
|
||||
|
|
@ -21,6 +23,7 @@ impl Checkbox {
|
|||
id: id.into(),
|
||||
base: div(),
|
||||
label: None,
|
||||
children: Vec::new(),
|
||||
checked: false,
|
||||
disabled: false,
|
||||
on_click: None,
|
||||
|
|
@ -66,6 +69,12 @@ impl Selectable for Checkbox {
|
|||
}
|
||||
}
|
||||
|
||||
impl ParentElement for Checkbox {
|
||||
fn extend(&mut self, elements: impl IntoIterator<Item = AnyElement>) {
|
||||
self.children.extend(elements);
|
||||
}
|
||||
}
|
||||
|
||||
impl RenderOnce for Checkbox {
|
||||
fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement {
|
||||
let (color, icon_color) = if self.disabled {
|
||||
|
|
@ -110,13 +119,26 @@ impl RenderOnce for Checkbox {
|
|||
}),
|
||||
),
|
||||
)
|
||||
.map(|this| {
|
||||
if let Some(label) = self.label {
|
||||
this.child(div().size_full().line_height(relative(1.)).child(label))
|
||||
} else {
|
||||
this
|
||||
}
|
||||
})
|
||||
.child(
|
||||
v_flex()
|
||||
.w_full()
|
||||
.line_height(relative(1.2))
|
||||
.gap_1()
|
||||
.map(|this| {
|
||||
if let Some(label) = self.label {
|
||||
this.child(
|
||||
div()
|
||||
.size_full()
|
||||
.text_color(cx.theme().foreground)
|
||||
.line_height(relative(1.))
|
||||
.child(label),
|
||||
)
|
||||
} else {
|
||||
this
|
||||
}
|
||||
})
|
||||
.children(self.children),
|
||||
)
|
||||
.when(self.disabled, |this| {
|
||||
this.cursor_not_allowed()
|
||||
.text_color(cx.theme().muted_foreground)
|
||||
|
|
|
|||
|
|
@ -2,9 +2,9 @@ use std::rc::Rc;
|
|||
|
||||
use crate::{h_flex, text::Text, v_flex, ActiveTheme, AxisExt, IconName};
|
||||
use gpui::{
|
||||
div, prelude::FluentBuilder, relative, svg, App, Axis, Div, ElementId, InteractiveElement,
|
||||
IntoElement, ParentElement, RenderOnce, SharedString, StatefulInteractiveElement,
|
||||
StyleRefinement, Styled, Window,
|
||||
div, prelude::FluentBuilder, relative, svg, AnyElement, App, Axis, Div, ElementId,
|
||||
InteractiveElement, IntoElement, ParentElement, RenderOnce, SharedString,
|
||||
StatefulInteractiveElement, StyleRefinement, Styled, Window,
|
||||
};
|
||||
|
||||
/// A Radio element.
|
||||
|
|
@ -15,6 +15,7 @@ pub struct Radio {
|
|||
base: Div,
|
||||
id: ElementId,
|
||||
label: Option<Text>,
|
||||
children: Vec<AnyElement>,
|
||||
checked: bool,
|
||||
disabled: bool,
|
||||
on_click: Option<Box<dyn Fn(&bool, &mut Window, &mut App) + 'static>>,
|
||||
|
|
@ -26,6 +27,7 @@ impl Radio {
|
|||
id: id.into(),
|
||||
base: div(),
|
||||
label: None,
|
||||
children: Vec::new(),
|
||||
checked: false,
|
||||
disabled: false,
|
||||
on_click: None,
|
||||
|
|
@ -59,6 +61,12 @@ impl Styled for Radio {
|
|||
}
|
||||
}
|
||||
|
||||
impl ParentElement for Radio {
|
||||
fn extend(&mut self, elements: impl IntoIterator<Item = AnyElement>) {
|
||||
self.children.extend(elements);
|
||||
}
|
||||
}
|
||||
|
||||
impl RenderOnce for Radio {
|
||||
fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement {
|
||||
let color = if self.disabled {
|
||||
|
|
@ -100,15 +108,22 @@ impl RenderOnce for Radio {
|
|||
}),
|
||||
),
|
||||
)
|
||||
.when_some(self.label, |this, label| {
|
||||
this.child(
|
||||
div()
|
||||
.size_full()
|
||||
.overflow_hidden()
|
||||
.line_height(relative(1.))
|
||||
.child(label),
|
||||
)
|
||||
})
|
||||
.child(
|
||||
v_flex()
|
||||
.w_full()
|
||||
.line_height(relative(1.2))
|
||||
.gap_1()
|
||||
.when_some(self.label, |this, label| {
|
||||
this.child(
|
||||
div()
|
||||
.size_full()
|
||||
.overflow_hidden()
|
||||
.line_height(relative(1.))
|
||||
.child(label),
|
||||
)
|
||||
})
|
||||
.children(self.children),
|
||||
)
|
||||
.when_some(
|
||||
self.on_click.filter(|_| !self.disabled),
|
||||
|this, on_click| {
|
||||
|
|
|
|||
Loading…
Reference in a new issue