From 6dbc12f6af863a55474706b3afdd502ee8aeedd7 Mon Sep 17 00:00:00 2001 From: Danilo Leal <67129314+danilo-leal@users.noreply.github.com> Date: Fri, 20 Dec 2024 20:44:47 -0300 Subject: [PATCH] Add the `SwitchWithLabel` component (#22314) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Screenshot 2024-12-20 at 8 31 14 PM Release Notes: - N/A --- crates/ui/src/components/toggle.rs | 75 +++++++++++++++++++++++++++ crates/workspace/src/theme_preview.rs | 15 +++--- 2 files changed, 83 insertions(+), 7 deletions(-) diff --git a/crates/ui/src/components/toggle.rs b/crates/ui/src/components/toggle.rs index 4d434b81ca75654423f47a0b30e03969141503f6..aa7e4b181a3d737809c9c8f53e06fe5f7e3a5e03 100644 --- a/crates/ui/src/components/toggle.rs +++ b/crates/ui/src/components/toggle.rs @@ -282,6 +282,52 @@ impl RenderOnce for Switch { } } +/// A [`Switch`] that has a [`Label`]. +#[derive(IntoElement)] +pub struct SwitchWithLabel { + id: ElementId, + label: Label, + checked: ToggleState, + on_click: Arc, +} + +impl SwitchWithLabel { + pub fn new( + id: impl Into, + label: Label, + checked: ToggleState, + on_click: impl Fn(&ToggleState, &mut WindowContext) + 'static, + ) -> Self { + Self { + id: id.into(), + label, + checked, + on_click: Arc::new(on_click), + } + } +} + +impl RenderOnce for SwitchWithLabel { + fn render(self, cx: &mut WindowContext) -> impl IntoElement { + h_flex() + .gap(DynamicSpacing::Base08.rems(cx)) + .child(Switch::new(self.id.clone(), self.checked).on_click({ + let on_click = self.on_click.clone(); + move |checked, cx| { + (on_click)(checked, cx); + } + })) + .child( + div() + .id(SharedString::from(format!("{}-label", self.id))) + .on_click(move |_event, cx| { + (self.on_click)(&self.checked.inverse(), cx); + }) + .child(self.label), + ) + } +} + impl ComponentPreview for Checkbox { fn description() -> impl Into> { "A checkbox lets people choose between a pair of opposing states, like enabled and disabled, using a different appearance to indicate each state." @@ -407,3 +453,32 @@ impl ComponentPreview for CheckboxWithLabel { ])] } } + +impl ComponentPreview for SwitchWithLabel { + fn description() -> impl Into> { + "A switch with an associated label, allowing users to select an option while providing a descriptive text." + } + + fn examples(_: &mut WindowContext) -> Vec> { + vec![example_group(vec![ + single_example( + "Off", + SwitchWithLabel::new( + "switch_with_label_unselected", + Label::new("Always save on quit"), + ToggleState::Unselected, + |_, _| {}, + ), + ), + single_example( + "On", + SwitchWithLabel::new( + "switch_with_label_selected", + Label::new("Always save on quit"), + ToggleState::Selected, + |_, _| {}, + ), + ), + ])] + } +} diff --git a/crates/workspace/src/theme_preview.rs b/crates/workspace/src/theme_preview.rs index 8ad8db05f57d3bc07215720c8fb108d7ef2b6275..3dc4b461503332b362a3720e022851293e826b1f 100644 --- a/crates/workspace/src/theme_preview.rs +++ b/crates/workspace/src/theme_preview.rs @@ -6,7 +6,7 @@ use ui::{ element_cell, prelude::*, string_cell, utils::calculate_contrast_ratio, AudioStatus, Availability, Avatar, AvatarAudioStatusIndicator, AvatarAvailabilityIndicator, ButtonLike, Checkbox, CheckboxWithLabel, ContentGroup, DecoratedIcon, ElevationIndex, Facepile, - IconDecoration, Indicator, Switch, Table, TintColor, Tooltip, + IconDecoration, Indicator, Switch, SwitchWithLabel, Table, TintColor, Tooltip, }; use crate::{Item, Workspace}; @@ -369,16 +369,17 @@ impl ThemePreview { .overflow_scroll() .size_full() .gap_2() - .child(Switch::render_component_previews(cx)) - .child(ContentGroup::render_component_previews(cx)) - .child(IconDecoration::render_component_previews(cx)) - .child(DecoratedIcon::render_component_previews(cx)) + .child(Button::render_component_previews(cx)) .child(Checkbox::render_component_previews(cx)) .child(CheckboxWithLabel::render_component_previews(cx)) + .child(ContentGroup::render_component_previews(cx)) + .child(DecoratedIcon::render_component_previews(cx)) .child(Facepile::render_component_previews(cx)) - .child(Button::render_component_previews(cx)) - .child(Indicator::render_component_previews(cx)) .child(Icon::render_component_previews(cx)) + .child(IconDecoration::render_component_previews(cx)) + .child(Indicator::render_component_previews(cx)) + .child(Switch::render_component_previews(cx)) + .child(SwitchWithLabel::render_component_previews(cx)) .child(Table::render_component_previews(cx)) }