fc_dioxus/components/
spinner.rs1use crate::{
3 core::{assets, attrs::component_attributes},
4 prelude::*,
5 theme::use_stylesheets,
6};
7const BEM: Bem = Bem::new("fc-spinner");
8const SHIMMER: Bem = Bem::new("fc-shimmer-text");
9const HIDDEN: Bem = Bem::new("fc-u-visually-hidden");
10fc_modifier! {
11 pub enum SpinnerKind for BEM {
13 Ring => None,
15 Arc => "arc",
17 Dots => "dots",
19 Pulse => "pulse",
21 Bars => "bars",
23 Orbit => "orbit",
25 Sparkle => "sparkle",
27 }
28}
29fc_modifier! {
30 pub enum SpinnerSize for BEM {
32 Md => None,
34 Xs => "xs",
36 Sm => "sm",
38 Lg => "lg",
40 Xl => "xl",
42 }
43}
44fc_modifier! {
45 pub enum SpinnerTone for BEM {
47 Accent => None,
49 Muted => "muted",
51 Current => "current",
53 }
54}
55
56#[derive(Debug, Clone, PartialEq, Eq)]
59pub enum SpinnerLabel {
60 Decorative,
62 Status(AccessibleName),
64}
65
66#[component]
68pub fn Spinner(
69 #[props(default)] kind: SpinnerKind,
70 #[props(default)] size: SpinnerSize,
71 #[props(default)] tone: SpinnerTone,
72 label: SpinnerLabel,
73 #[props(default)] class: Option<String>,
74 #[props(extends = GlobalAttributes)] attributes: Vec<Attribute>,
75) -> Element {
76 let classes = ClassList::new(BEM.block())
77 .with_modifier(BEM, kind)
78 .with_modifier(BEM, size)
79 .with_modifier(BEM, tone)
80 .extend(class.as_deref());
81 let attributes = component_attributes(attributes, classes, &["aria-hidden", "role"]);
82 let parts = match kind {
84 SpinnerKind::Dots => 3,
85 SpinnerKind::Bars => 4,
86 _ => 0,
87 };
88 let drawing = rsx! {
89 span { aria_hidden: "true", ..attributes,
90 for index in 0..parts { span { key: "{index}" } }
91 }
92 };
93 rsx! {
94 if use_stylesheets() { document::Stylesheet { href: assets::COMPONENTS_SPINNER_CSS } }
95 match label {
96 SpinnerLabel::Decorative => drawing,
97 SpinnerLabel::Status(name) => rsx! {
98 span { role: "status", {drawing} span { class: HIDDEN.block(), "{name}" } }
99 },
100 }
101 }
102}
103
104#[component]
106pub fn ShimmerText(
107 #[props(default)] class: Option<String>,
108 #[props(extends = GlobalAttributes)] attributes: Vec<Attribute>,
109 children: Element,
110) -> Element {
111 let attributes = component_attributes(
112 attributes,
113 ClassList::new(SHIMMER.block()).extend(class.as_deref()),
114 &[],
115 );
116 rsx! {
117 if use_stylesheets() { document::Stylesheet { href: assets::COMPONENTS_SPINNER_CSS } }
118 span { ..attributes, {children} }
119 }
120}