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_val = crate::theme::use_theme()();
16    #[cfg(feature = "theme")]
17    let track_checked_modifier = match &theme_val.primary_color {
18        crate::theme::PrimaryColor::Violet => "sd-switch__track--checked".to_string(),
19        crate::theme::PrimaryColor::Obsidian => "sd-switch__track--checked-obsidian".to_string(),
20        crate::theme::PrimaryColor::Crimson => "sd-switch__track--checked-crimson".to_string(),
21        crate::theme::PrimaryColor::Cyan => "sd-switch__track--checked-cyan".to_string(),
22        crate::theme::PrimaryColor::Emerald => "sd-switch__track--checked-emerald".to_string(),
23        crate::theme::PrimaryColor::Custom { .. } => {
24            format!("sd-switch__track--checked-{}", theme_val.primary_color.css_prefix())
25        }
26    };
27    #[cfg(feature = "theme")]
28    let glow_modifier = if is_checked {
29        theme_val.resolve_elevation_class("switch", glow)
30    } else {
31        String::new()
32    };
33    #[cfg(feature = "theme")]
34    let base_override = theme_val.resolve_component_base("switch").unwrap_or("");
35    #[cfg(feature = "theme")]
36    let class_modifiers = theme_val.resolve_class_modifiers("switch", &class);
37
38    #[cfg(not(feature = "theme"))]
39    let base_override = "";
40    #[cfg(not(feature = "theme"))]
41    let class_modifiers = String::new();
42    #[cfg(not(feature = "theme"))]
43    let track_checked_modifier = "sd-switch__track--checked".to_string();
44    #[cfg(not(feature = "theme"))]
45    let glow_modifier = if is_checked && glow.unwrap_or(false) {
46        "sd-switch__track--glow".to_string()
47    } else {
48        String::new()
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 {base_override} {disabled_class} {class_modifiers} {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}