Skip to main content

orbital_base_components/form/switch/
base.rs

1use leptos::{html, prelude::*};
2
3use crate::form::bind::FormBind;
4use crate::form::field_injection::{new_field_id, FieldInjection};
5
6/// Headless switch — `role="switch"` checkbox input and indicator.
7#[component(transparent)]
8pub fn BaseSwitch(
9    #[prop(optional, into)] class: MaybeProp<String>,
10    #[prop(optional, into)] id: MaybeProp<String>,
11    #[prop(optional, into)] name: MaybeProp<String>,
12    #[prop(optional, into)] value: MaybeProp<String>,
13    #[prop(optional, into)] checked: FormBind<bool>,
14    #[prop(optional, into)] label: MaybeProp<String>,
15) -> impl IntoView {
16    let (id, name) = FieldInjection::use_id_and_name(id, name);
17    let fallback_id = StoredValue::new(new_field_id());
18    let resolved_id = Signal::derive(move || id.get().unwrap_or_else(|| fallback_id.get_value()));
19    let input_ref = NodeRef::<html::Input>::new();
20
21    let checked_bind = checked.clone();
22    let on_change = move |_| {
23        if let Some(input) = input_ref.get_untracked() {
24            checked_bind.set(input.checked());
25        }
26    };
27
28    view! {
29        <div class=move || class.get().unwrap_or_default()>
30            <input
31                type="checkbox"
32                role="switch"
33                id=resolved_id
34                name=name
35                value=move || value.get()
36                prop:checked=move || checked.get()
37                node_ref=input_ref
38                on:change=on_change
39            />
40            <div aria-hidden="true" role="presentation"></div>
41            {move || {
42                label.get().map(|text| {
43                    view! {
44                        <label for=resolved_id.get()>{text}</label>
45                    }
46                })
47            }}
48        </div>
49    }
50}