ui: Add the SwitchField
component (#34713)
This will be useful for both the current agent panel and some other onboarding stuff we're working on. Also ended up removing the `SwitchWithLabel` as it was unused. Release Notes: - N/A
This commit is contained in:
parent
87555d3f0b
commit
64ce696aae
1 changed files with 142 additions and 24 deletions
|
@ -543,28 +543,48 @@ impl RenderOnce for Switch {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A [`Switch`] that has a [`Label`].
|
/// # SwitchField
|
||||||
#[derive(IntoElement)]
|
///
|
||||||
pub struct SwitchWithLabel {
|
/// A field component that combines a label, description, and switch into one reusable component.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use ui::prelude::*;
|
||||||
|
///
|
||||||
|
/// SwitchField::new(
|
||||||
|
/// "feature-toggle",
|
||||||
|
/// "Enable feature",
|
||||||
|
/// "This feature adds new functionality to the app.",
|
||||||
|
/// ToggleState::Unselected,
|
||||||
|
/// |state, window, cx| {
|
||||||
|
/// // Logic here
|
||||||
|
/// }
|
||||||
|
/// );
|
||||||
|
/// ```
|
||||||
|
#[derive(IntoElement, RegisterComponent)]
|
||||||
|
pub struct SwitchField {
|
||||||
id: ElementId,
|
id: ElementId,
|
||||||
label: Label,
|
label: SharedString,
|
||||||
|
description: SharedString,
|
||||||
toggle_state: ToggleState,
|
toggle_state: ToggleState,
|
||||||
on_click: Arc<dyn Fn(&ToggleState, &mut Window, &mut App) + 'static>,
|
on_click: Arc<dyn Fn(&ToggleState, &mut Window, &mut App) + 'static>,
|
||||||
disabled: bool,
|
disabled: bool,
|
||||||
color: SwitchColor,
|
color: SwitchColor,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SwitchWithLabel {
|
impl SwitchField {
|
||||||
/// Creates a switch with an attached label.
|
|
||||||
pub fn new(
|
pub fn new(
|
||||||
id: impl Into<ElementId>,
|
id: impl Into<ElementId>,
|
||||||
label: Label,
|
label: impl Into<SharedString>,
|
||||||
|
description: impl Into<SharedString>,
|
||||||
toggle_state: impl Into<ToggleState>,
|
toggle_state: impl Into<ToggleState>,
|
||||||
on_click: impl Fn(&ToggleState, &mut Window, &mut App) + 'static,
|
on_click: impl Fn(&ToggleState, &mut Window, &mut App) + 'static,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
id: id.into(),
|
id: id.into(),
|
||||||
label,
|
label: label.into(),
|
||||||
|
description: description.into(),
|
||||||
toggle_state: toggle_state.into(),
|
toggle_state: toggle_state.into(),
|
||||||
on_click: Arc::new(on_click),
|
on_click: Arc::new(on_click),
|
||||||
disabled: false,
|
disabled: false,
|
||||||
|
@ -572,43 +592,141 @@ impl SwitchWithLabel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the disabled state of the [`SwitchWithLabel`].
|
|
||||||
pub fn disabled(mut self, disabled: bool) -> Self {
|
pub fn disabled(mut self, disabled: bool) -> Self {
|
||||||
self.disabled = disabled;
|
self.disabled = disabled;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the color of the switch using the specified [`SwitchColor`].
|
/// Sets the color of the switch using the specified [`SwitchColor`].
|
||||||
|
/// This changes the color scheme of the switch when it's in the "on" state.
|
||||||
pub fn color(mut self, color: SwitchColor) -> Self {
|
pub fn color(mut self, color: SwitchColor) -> Self {
|
||||||
self.color = color;
|
self.color = color;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RenderOnce for SwitchWithLabel {
|
impl RenderOnce for SwitchField {
|
||||||
fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
|
fn render(self, _window: &mut Window, _cx: &mut App) -> impl IntoElement {
|
||||||
h_flex()
|
h_flex()
|
||||||
.id(SharedString::from(format!("{}-container", self.id)))
|
.id(SharedString::from(format!("{}-container", self.id)))
|
||||||
.gap(DynamicSpacing::Base08.rems(cx))
|
.w_full()
|
||||||
|
.gap_4()
|
||||||
|
.justify_between()
|
||||||
|
.flex_wrap()
|
||||||
.child(
|
.child(
|
||||||
Switch::new(self.id.clone(), self.toggle_state)
|
v_flex()
|
||||||
.disabled(self.disabled)
|
.gap_0p5()
|
||||||
.color(self.color)
|
.max_w_5_6()
|
||||||
.on_click({
|
.child(Label::new(self.label))
|
||||||
let on_click = self.on_click.clone();
|
.child(Label::new(self.description).color(Color::Muted)),
|
||||||
move |checked, window, cx| {
|
|
||||||
(on_click)(checked, window, cx);
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
)
|
)
|
||||||
.child(
|
.child(
|
||||||
div()
|
Switch::new(
|
||||||
.id(SharedString::from(format!("{}-label", self.id)))
|
SharedString::from(format!("{}-switch", self.id)),
|
||||||
.child(self.label),
|
self.toggle_state,
|
||||||
|
)
|
||||||
|
.color(self.color)
|
||||||
|
.disabled(self.disabled)
|
||||||
|
.on_click({
|
||||||
|
let on_click = self.on_click.clone();
|
||||||
|
move |state, window, cx| {
|
||||||
|
(on_click)(state, window, cx);
|
||||||
|
}
|
||||||
|
}),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Component for SwitchField {
|
||||||
|
fn scope() -> ComponentScope {
|
||||||
|
ComponentScope::Input
|
||||||
|
}
|
||||||
|
|
||||||
|
fn description() -> Option<&'static str> {
|
||||||
|
Some("A field component that combines a label, description, and switch")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn preview(_window: &mut Window, _cx: &mut App) -> Option<AnyElement> {
|
||||||
|
Some(
|
||||||
|
v_flex()
|
||||||
|
.gap_6()
|
||||||
|
.children(vec![
|
||||||
|
example_group_with_title(
|
||||||
|
"States",
|
||||||
|
vec![
|
||||||
|
single_example(
|
||||||
|
"Unselected",
|
||||||
|
SwitchField::new(
|
||||||
|
"switch_field_unselected",
|
||||||
|
"Enable notifications",
|
||||||
|
"Receive notifications when new messages arrive.",
|
||||||
|
ToggleState::Unselected,
|
||||||
|
|_, _, _| {},
|
||||||
|
)
|
||||||
|
.into_any_element(),
|
||||||
|
),
|
||||||
|
single_example(
|
||||||
|
"Selected",
|
||||||
|
SwitchField::new(
|
||||||
|
"switch_field_selected",
|
||||||
|
"Enable notifications",
|
||||||
|
"Receive notifications when new messages arrive.",
|
||||||
|
ToggleState::Selected,
|
||||||
|
|_, _, _| {},
|
||||||
|
)
|
||||||
|
.into_any_element(),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
example_group_with_title(
|
||||||
|
"Colors",
|
||||||
|
vec![
|
||||||
|
single_example(
|
||||||
|
"Default",
|
||||||
|
SwitchField::new(
|
||||||
|
"switch_field_default",
|
||||||
|
"Default color",
|
||||||
|
"This uses the default switch color.",
|
||||||
|
ToggleState::Selected,
|
||||||
|
|_, _, _| {},
|
||||||
|
)
|
||||||
|
.into_any_element(),
|
||||||
|
),
|
||||||
|
single_example(
|
||||||
|
"Accent",
|
||||||
|
SwitchField::new(
|
||||||
|
"switch_field_accent",
|
||||||
|
"Accent color",
|
||||||
|
"This uses the accent color scheme.",
|
||||||
|
ToggleState::Selected,
|
||||||
|
|_, _, _| {},
|
||||||
|
)
|
||||||
|
.color(SwitchColor::Accent)
|
||||||
|
.into_any_element(),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
example_group_with_title(
|
||||||
|
"Disabled",
|
||||||
|
vec![single_example(
|
||||||
|
"Disabled",
|
||||||
|
SwitchField::new(
|
||||||
|
"switch_field_disabled",
|
||||||
|
"Disabled field",
|
||||||
|
"This field is disabled and cannot be toggled.",
|
||||||
|
ToggleState::Selected,
|
||||||
|
|_, _, _| {},
|
||||||
|
)
|
||||||
|
.disabled(true)
|
||||||
|
.into_any_element(),
|
||||||
|
)],
|
||||||
|
),
|
||||||
|
])
|
||||||
|
.into_any_element(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Component for Checkbox {
|
impl Component for Checkbox {
|
||||||
fn scope() -> ComponentScope {
|
fn scope() -> ComponentScope {
|
||||||
ComponentScope::Input
|
ComponentScope::Input
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue