Skip to main content

yggdrasil/components/skeletons/
post_detail_skeleton.rs

1//! 文章详情页骨架屏
2//!
3//! 与文章页逐块对齐:面包屑、两行标题、元信息、发丝线与正文段落。
4
5use crate::components::skeletons::atoms::*;
6use leptos::prelude::*;
7
8/// 正文段落占位的宽度,错落排布更像真实段落。
9const PARAGRAPH_WIDTHS: [&str; 8] = [
10    "width: 100%",
11    "width: 96%",
12    "width: 88%",
13    "width: 100%",
14    "width: 72%",
15    "width: 94%",
16    "width: 100%",
17    "width: 60%",
18];
19
20/// 文章详情/预览页共享的正文骨架屏片段。供 [`PostDetailSkeleton`] 与
21/// [`crate::components::skeletons::post_preview_skeleton::PostPreviewSkeleton`]
22/// 复用,两者视觉上唯一差异是预览页顶部多一段预览横幅。
23#[component]
24pub fn PostDetailBody() -> impl IntoView {
25    view! {
26        <div class="post-header">
27            <SkeletonBox class="h-3 w-28"/>
28            <SkeletonBox class="post-skeleton-title mt-5"/>
29            <SkeletonBox class="post-skeleton-title mt-2.5 w-3/5"/>
30            <SkeletonBox class="h-3 mt-6 w-72 max-w-full"/>
31        </div>
32        <div class="post-skeleton-body">
33            {PARAGRAPH_WIDTHS
34                .iter()
35                .map(|width| view! { <SkeletonBox class="h-3.5" style=*width/> })
36                .collect_view()}
37            <SkeletonBox class="post-skeleton-block"/>
38        </div>
39    }
40}
41
42/// 文章详情页骨架屏组件。
43#[component]
44pub fn PostDetailSkeleton() -> impl IntoView {
45    view! {
46        <div class="post-layout">
47            <article class="post-single" role="status" aria-label="正在加载文章">
48                <PostDetailBody/>
49            </article>
50        </div>
51    }
52}