Skip to main content

dioxus_element_plug/components/
skeleton.rs

1use dioxus::prelude::*;
2
3/// Skeleton props
4#[derive(Props, Clone, PartialEq)]
5pub struct SkeletonProps {
6    /// Real content to show when not loading
7    #[props(default)]
8    pub children: Option<Element>,
9
10    /// Whether showing animation
11    #[props(default = false)]
12    pub animated: bool,
13
14    /// Number of fake items to render
15    #[props(default = 1)]
16    pub count: u32,
17
18    /// Number of rows per item
19    #[props(default = 3)]
20    pub rows: u32,
21
22    /// Whether showing the real DOM
23    #[props(default = true)]
24    pub loading: bool,
25
26    /// Additional CSS classes
27    #[props(default)]
28    pub class: Option<String>,
29
30    /// Inline styles
31    #[props(default)]
32    pub style: Option<String>,
33}
34
35/// Skeleton component for displaying loading placeholders
36///
37/// ## Example
38///
39/// ```rust,ignore
40/// rsx! {
41///     Skeleton { animated: true, rows: 3, loading: true }
42/// }
43/// ```
44#[component]
45pub fn Skeleton(props: SkeletonProps) -> Element {
46    if !props.loading {
47        return rsx! { {props.children} };
48    }
49
50    let mut class_names = vec!["el-skeleton".to_string()];
51
52    if props.animated {
53        class_names.push("is-animated".to_string());
54    }
55
56    if let Some(ref custom_class) = props.class {
57        class_names.push(custom_class.clone());
58    }
59
60    let class_string = class_names.join(" ");
61    let style_string = props.style.clone().unwrap_or_default();
62
63    let items: Vec<u32> = (0..props.count).collect();
64    let rows: Vec<(u32, String)> = (0..props.rows)
65        .map(|idx| {
66            let width = if idx == props.rows - 1 { "50%" } else { "100%" };
67            (idx, width.to_string())
68        })
69        .collect();
70
71    rsx! {
72        div {
73            class: "{class_string}",
74            style: "{style_string}",
75            for _item in items.iter() {
76                div {
77                    class: "el-skeleton__item",
78                    for (_idx, width) in rows.iter() {
79                        div {
80                            class: "el-skeleton__paragraph",
81                            style: "width: {width}; height: 16px; margin-top: 12px; background: var(--el-fill-color-light); border-radius: 4px;",
82                        }
83                    }
84                }
85            }
86        }
87    }
88}
89