use crate::{
core::{assets, attrs::component_attributes},
prelude::*,
theme::use_stylesheets,
};
const BEM: Bem = Bem::new("fc-spinner");
const SHIMMER: Bem = Bem::new("fc-shimmer-text");
const HIDDEN: Bem = Bem::new("fc-u-visually-hidden");
fc_modifier! {
pub enum SpinnerKind for BEM {
Ring => None,
Arc => "arc",
Dots => "dots",
Pulse => "pulse",
Bars => "bars",
Orbit => "orbit",
Sparkle => "sparkle",
}
}
fc_modifier! {
pub enum SpinnerSize for BEM {
Md => None,
Xs => "xs",
Sm => "sm",
Lg => "lg",
Xl => "xl",
}
}
fc_modifier! {
pub enum SpinnerTone for BEM {
Accent => None,
Muted => "muted",
Current => "current",
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum SpinnerLabel {
Decorative,
Status(AccessibleName),
}
#[component]
pub fn Spinner(
#[props(default)] kind: SpinnerKind,
#[props(default)] size: SpinnerSize,
#[props(default)] tone: SpinnerTone,
label: SpinnerLabel,
#[props(default)] class: Option<String>,
#[props(extends = GlobalAttributes)] attributes: Vec<Attribute>,
) -> Element {
let classes = ClassList::new(BEM.block())
.with_modifier(BEM, kind)
.with_modifier(BEM, size)
.with_modifier(BEM, tone)
.extend(class.as_deref());
let attributes = component_attributes(attributes, classes, &["aria-hidden", "role"]);
let parts = match kind {
SpinnerKind::Dots => 3,
SpinnerKind::Bars => 4,
_ => 0,
};
let drawing = rsx! {
span { aria_hidden: "true", ..attributes,
for index in 0..parts { span { key: "{index}" } }
}
};
rsx! {
if use_stylesheets() { document::Stylesheet { href: assets::COMPONENTS_SPINNER_CSS } }
match label {
SpinnerLabel::Decorative => drawing,
SpinnerLabel::Status(name) => rsx! {
span { role: "status", {drawing} span { class: HIDDEN.block(), "{name}" } }
},
}
}
}
#[component]
pub fn ShimmerText(
#[props(default)] class: Option<String>,
#[props(extends = GlobalAttributes)] attributes: Vec<Attribute>,
children: Element,
) -> Element {
let attributes = component_attributes(
attributes,
ClassList::new(SHIMMER.block()).extend(class.as_deref()),
&[],
);
rsx! {
if use_stylesheets() { document::Stylesheet { href: assets::COMPONENTS_SPINNER_CSS } }
span { ..attributes, {children} }
}
}