Skip to main content

yggdrasil/components/skeletons/
archive_skeleton.rs

1//! 归档与标签详情骨架屏:与真实版式逐块对齐(摘要行、标签区、年份分组)。
2
3use leptos::prelude::*;
4
5use crate::components::skeletons::atoms::SkeletonBox;
6use crate::pages::tags::TagIntro;
7
8/// 标签占位的宽度,错落排布更像真实标签。
9const CHIP_WIDTHS: [&str; 10] = [
10    "width: 4.5rem",
11    "width: 3.5rem",
12    "width: 5.5rem",
13    "width: 4rem",
14    "width: 6rem",
15    "width: 3.75rem",
16    "width: 5rem",
17    "width: 4.25rem",
18    "width: 3.25rem",
19    "width: 5.25rem",
20];
21/// 文章行标题的宽度。
22const ROW_WIDTHS: [&str; 5] = [
23    "width: 72%",
24    "width: 58%",
25    "width: 80%",
26    "width: 64%",
27    "width: 50%",
28];
29
30/// 归档页整页占位:页标题之下的全部区块。
31#[component]
32pub fn ArchiveSkeleton() -> impl IntoView {
33    view! {
34        <div class="archive">
35            <header class="archive-header">
36                <h1 class="archive-title">"归档"</h1>
37            </header>
38            <ArchiveBodySkeleton/>
39        </div>
40    }
41}
42
43/// 标签详情整页占位:开场照常显示,只有数据区占位。
44#[component]
45pub fn TagDetailSkeleton(#[prop(into)] tag: String) -> impl IntoView {
46    view! {
47        <div class="archive">
48            <TagIntro tag=tag/>
49            <ArchiveBodySkeleton/>
50        </div>
51    }
52}
53
54/// 摘要行、标签区与两个年份分组的占位。
55#[component]
56pub fn ArchiveBodySkeleton() -> impl IntoView {
57    view! {
58        <div role="status" aria-label="正在加载文章">
59            <div aria-hidden="true">
60                <SkeletonBox class="archive-summary h-4 w-60 max-w-full"/>
61                <div class="archive-tags">
62                    <div class="archive-tags-head">
63                        <SkeletonBox class="h-3 w-14"/>
64                    </div>
65                    <div class="archive-tags-list">
66                        {CHIP_WIDTHS
67                            .iter()
68                            .map(|width| view! { <SkeletonBox class="h-7 rounded-full" style=*width/> })
69                            .collect_view()}
70                    </div>
71                </div>
72                <div class="archive-years">
73                    {(0..2)
74                        .map(|_| {
75                            view! {
76                                <div class="archive-year">
77                                    <div class="archive-year-label">
78                                        <SkeletonBox class="h-8 w-20"/>
79                                        <SkeletonBox class="h-3 w-10 mt-2"/>
80                                    </div>
81                                    <div class="archive-rows">
82                                        {ROW_WIDTHS
83                                            .iter()
84                                            .map(|width| {
85                                                view! {
86                                                    <div class="archive-entry archive-entry-skeleton">
87                                                        <SkeletonBox class="h-3 w-10"/>
88                                                        <SkeletonBox class="h-4" style=*width/>
89                                                    </div>
90                                                }
91                                            })
92                                            .collect_view()}
93                                    </div>
94                                </div>
95                            }
96                        })
97                        .collect_view()}
98                </div>
99            </div>
100        </div>
101    }
102}