Components

Switch

Documentation

Switches allow users to toggle between two mutually exclusive states

use leptos::prelude::*;
use tailwind_fuse::*;

use crate::behavior::{SwitchRoot, SwitchThumb};

#[derive(TwClass)]
#[tw(
    class = "inline-flex shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=unchecked]:bg-input"
)]
struct SwitchRootStyle {
    size: SwitchSize,
}

#[derive(TwClass)]
#[tw(
    class = "pointer-events-none block rounded-full bg-background shadow-lg ring-0 transition-transform data-[state=unchecked]:translate-x-0"
)]
struct SwitchThumbStyle {
    size: SwitchThumbSize,
}

#[derive(TwVariant)]
pub enum SwitchSize {
    #[tw(default, class = "h-6 w-11")]
    Default,
    #[tw(class = "h-5 w-9")]
    Sm,
    #[tw(class = "h-7 w-14")]
    Lg,
}

#[derive(TwVariant)]
enum SwitchThumbSize {
    #[tw(default, class = "h-5 w-5 data-[state=checked]:translate-x-5")]
    Default,
    #[tw(class = "h-4 w-4 data-[state=checked]:translate-x-4")]
    Sm,
    #[tw(class = "h-6 w-6 data-[state=checked]:translate-x-7")]
    Lg,
}

/// A styled switch component for toggling between checked and unchecked states
#[component]
pub fn Switch(
    #[prop(optional)] class: &'static str,
    #[prop(optional)] size: SwitchSize,
    #[prop(optional)] checked: RwSignal<bool>,
    #[prop(into, default = Signal::stored(false))] disabled: Signal<bool>,
    #[prop(optional_no_strip, into)] id: Option<&'static str>,
    #[prop(optional_no_strip, into)] name: Option<&'static str>,
) -> impl IntoView {
    let final_class = SwitchRootStyle { size }.with_class(class);

    let thumb_size = match size {
        SwitchSize::Sm => SwitchThumbSize::Sm,
        SwitchSize::Default => SwitchThumbSize::Default,
        SwitchSize::Lg => SwitchThumbSize::Lg,
    };

    let thumb_classes = SwitchThumbStyle { size: thumb_size }.to_class();

    view! {
        <SwitchRoot checked=checked disabled=disabled id=id name=name class=final_class>
            <SwitchThumb class=Signal::stored(thumb_classes) />
        </SwitchRoot>
    }
}
Click to expand