orbital-base-components 0.1.1

Headless base primitives for Orbital — structure, semantics, and accessibility
Documentation
use leptos::prelude::*;

#[derive(Clone, Copy, Default, PartialEq, Eq)]
pub enum SpinnerSize {
    ExtraTiny,
    Tiny,
    ExtraSmall,
    Small,
    #[default]
    Medium,
    Large,
    ExtraLarge,
    Huge,
}

impl SpinnerSize {
    pub fn as_str(&self) -> &'static str {
        match self {
            Self::ExtraTiny => "extra-tiny",
            Self::Tiny => "tiny",
            Self::ExtraSmall => "extra-small",
            Self::Small => "small",
            Self::Medium => "medium",
            Self::Large => "large",
            Self::ExtraLarge => "extra-large",
            Self::Huge => "huge",
        }
    }
}

#[component]
pub fn BaseSpinner(
    #[prop(optional, into)] class: MaybeProp<String>,
    #[prop(optional, into)] label: MaybeProp<String>,
    #[prop(optional, into)] size: Signal<SpinnerSize>,
    #[prop(optional)] children: Option<Children>,
) -> impl IntoView {
    let id = StoredValue::new(uuid::Uuid::new_v4().to_string());
    let spinner_label = label;
    let children_flag = children.is_some();
    let labelledby = move || {
        spinner_label.with(|label| {
            if label.is_some() || children_flag {
                Some(id.get_value())
            } else {
                None
            }
        })
    };

    view! {
        <div
            class=move || {
                let mut parts = vec![
                    "orbital-spinner".to_string(),
                    format!("orbital-spinner--{}", size.get().as_str()),
                ];
                if let Some(extra) = class.get() {
                    if !extra.is_empty() {
                        parts.push(extra);
                    }
                }
                parts.join(" ")
            }
            role="progressbar"
            aria-labelledby=labelledby
        >
            <span class="orbital-spinner__spinner" aria-hidden="true">
                <span class="orbital-spinner__spinner-tail"></span>
            </span>
            {label.get().map(|text| view! {
                <span class="orbital-spinner__label" id=id.get_value()>{text}</span>
            })}
            {children.map(|children| view! {
                <span class="orbital-spinner__label" id=id.get_value()>{children()}</span>
            })}
        </div>
    }
}