radix_leptos_toggle/
toggle.rs

1use leptos::{ev::MouseEvent, html::AnyElement, *};
2use radix_leptos_primitive::{compose_callbacks, Primitive};
3use radix_leptos_use_controllable_state::{use_controllable_state, UseControllableStateParams};
4
5#[component]
6pub fn Toggle(
7    /// The controlled state of the toggle.
8    #[prop(into, optional)]
9    pressed: MaybeProp<bool>,
10    /// The state of the toggle when initially rendered. Use `default_pressed` if you do not need to control the state of the toggle. Defaults to `false`.
11    #[prop(into, optional)]
12    default_pressed: MaybeProp<bool>,
13    /// The callback that fires when the state of the toggle changes.
14    #[prop(into, optional)]
15    on_pressed_change: Option<Callback<bool>>,
16    #[prop(into, optional)] disabled: MaybeProp<bool>,
17    #[prop(into, optional)] on_click: Option<Callback<MouseEvent>>,
18    #[prop(into, optional)] as_child: MaybeProp<bool>,
19    #[prop(optional)] node_ref: NodeRef<AnyElement>,
20    #[prop(attrs)] attrs: Vec<(&'static str, Attribute)>,
21    children: ChildrenFn,
22) -> impl IntoView {
23    let disabled = Signal::derive(move || disabled.get().unwrap_or(false));
24
25    let (pressed, set_pressed) = use_controllable_state(UseControllableStateParams {
26        prop: pressed,
27        on_change: on_pressed_change.map(|on_pressed_change| {
28            Callback::new(move |value| {
29                if let Some(value) = value {
30                    on_pressed_change.call(value);
31                }
32            })
33        }),
34        default_prop: default_pressed,
35    });
36    let pressed = Signal::derive(move || pressed.get().unwrap_or(false));
37
38    let mut attrs = attrs.clone();
39    attrs.extend([
40        ("aria-pressed", pressed.into_attribute()),
41        (
42            "data-state",
43            (move || match pressed.get() {
44                true => "on",
45                false => "off",
46            })
47            .into_attribute(),
48        ),
49        (
50            "data-disabled",
51            (move || disabled.get().then_some("")).into_attribute(),
52        ),
53        (
54            "disabled",
55            (move || disabled.get().then_some("")).into_attribute(),
56        ),
57    ]);
58
59    view! {
60        <Primitive
61            element=html::button
62            as_child=as_child
63            node_ref=node_ref
64            attrs=attrs
65            on:click=compose_callbacks(on_click, Some(Callback::new(move |_| {
66                if !disabled.get() {
67                    set_pressed.call(Some(!pressed.get()));
68                }
69            })), None)
70        >
71            {children()}
72        </Primitive>
73    }
74}