Skip to main content

shadow_design/
switch.rs

1use dioxus::prelude::*;
2
3#[component]
4pub fn Switch(
5    checked: Signal<bool>,
6    #[props(default)] label: Option<String>,
7    #[props(default)] description: Option<String>,
8    #[props(default)] disabled: bool,
9    #[props(default)] glow: Option<bool>,
10    #[props(default)] class: String,
11) -> Element {
12    let is_checked = *checked.read();
13
14    #[cfg(feature = "theme")]
15    let theme = crate::theme::use_theme();
16    #[cfg(feature = "theme")]
17    let has_glow = theme().is_component_glow_enabled("switch", glow);
18    #[cfg(not(feature = "theme"))]
19    let has_glow = glow.unwrap_or(false);
20
21    #[cfg(feature = "theme")]
22    let (track_checked_modifier, glow_modifier) = match theme().primary_color {
23        crate::theme::PrimaryColor::Violet => (
24            "sd-switch__track--checked",
25            if has_glow { "sd-switch__track--glow" } else { "" },
26        ),
27        crate::theme::PrimaryColor::Obsidian => (
28            "sd-switch__track--checked-obsidian",
29            if has_glow { "sd-switch__track--glow-obsidian" } else { "" },
30        ),
31        crate::theme::PrimaryColor::Crimson => (
32            "sd-switch__track--checked-crimson",
33            if has_glow { "sd-switch__track--glow-crimson" } else { "" },
34        ),
35        crate::theme::PrimaryColor::Cyan => (
36            "sd-switch__track--checked-cyan",
37            if has_glow { "sd-switch__track--glow-cyan" } else { "" },
38        ),
39        crate::theme::PrimaryColor::Emerald => (
40            "sd-switch__track--checked-emerald",
41            if has_glow { "sd-switch__track--glow-emerald" } else { "" },
42        ),
43    };
44
45    #[cfg(not(feature = "theme"))]
46    let (track_checked_modifier, glow_modifier) = (
47        "sd-switch__track--checked",
48        if has_glow { "sd-switch__track--glow" } else { "" },
49    );
50
51    let track_active_class = if is_checked {
52        format!("{track_checked_modifier} {glow_modifier}")
53    } else {
54        String::new()
55    };
56
57    let thumb_active_class = if is_checked {
58        "sd-switch__thumb--checked"
59    } else {
60        ""
61    };
62
63    let disabled_class = if disabled { "sd-switch--disabled" } else { "" };
64
65    rsx! {
66        div {
67            class: "sd-switch {disabled_class} {class}",
68            onclick: move |_| {
69                if !disabled {
70                    let next = !*checked.read();
71                    *checked.write() = next;
72                }
73            },
74            div {
75                class: "sd-switch__track {track_active_class}",
76                span {
77                    class: "sd-switch__thumb {thumb_active_class}",
78                }
79            }
80            if label.is_some() || description.is_some() {
81                div { class: "sd-switch__label-group",
82                    if let Some(lbl) = label {
83                        span { class: "sd-switch__label", "{lbl}" }
84                    }
85                    if let Some(desc) = description {
86                        span { class: "sd-switch__description", "{desc}" }
87                    }
88                }
89            }
90        }
91    }
92}