Skip to main content

yggdrasil/components/post/
breadcrumbs.rs

1//! 面包屑组件
2//!
3//! 文章标题上方的「文章 / 所在栏目」:「文章」回到首页,栏目取文章的第一个标签。
4
5use leptos::ev::MouseEvent;
6use leptos::prelude::*;
7
8use crate::routes::Route;
9
10/// 面包屑导航组件。
11///
12/// Props:
13/// - `tag`:所在栏目(文章的第一个标签),没有时只显示「文章」;可传 `String`、
14///   `Option<String>` 或省略
15/// - `sample`:图鉴展示非跳转的样例链接;正式文章默认 false。
16#[component]
17pub(super) fn Breadcrumbs(
18    #[prop(optional, into)] tag: MaybeProp<String>,
19    #[prop(optional)] sample: bool,
20) -> impl IntoView {
21    let home = if sample {
22        view! { <a href="#" on:click=|event: MouseEvent| event.prevent_default()>"文章"</a> }
23            .into_any()
24    } else {
25        view! { <a href=Route::Home.to_string() data-vt-return="true">"文章"</a> }.into_any()
26    };
27    let tag = tag.get_untracked().map(|tag| {
28        let link = if sample {
29            let label = tag.clone();
30            view! { <a href="#" on:click=|event: MouseEvent| event.prevent_default()>{label}</a> }
31                .into_any()
32        } else {
33            let href = Route::TagDetail { tag: tag.clone() }.to_string();
34            view! { <a href=href>{tag}</a> }.into_any()
35        };
36        view! {
37            <span class="post-crumbs-sep" aria-hidden="true">"/"</span>
38            {link}
39        }
40    });
41    view! {
42        <nav class="post-crumbs" aria-label="面包屑">
43            {home}
44            {tag}
45        </nav>
46    }
47}
48
49#[cfg(test)]
50mod tests {
51    use super::*;
52    use leptos::reactive::owner::Owner;
53
54    #[test]
55    fn links_home_and_first_tag() {
56        let html =
57            Owner::new().with(|| view! { <Breadcrumbs tag="Rust 编程".to_string()/> }.to_html());
58        assert!(html.contains(r#"href="/""#), "{html}");
59        assert!(html.contains(r#"data-vt-return="true""#), "{html}");
60        assert!(html.contains("/tags/Rust%20%E7%BC%96%E7%A8%8B"), "{html}");
61        assert!(html.contains("post-crumbs-sep"), "{html}");
62    }
63
64    #[test]
65    fn without_tag_only_shows_home() {
66        let html = Owner::new().with(|| view! { <Breadcrumbs/> }.to_html());
67        assert!(!html.contains("post-crumbs-sep"), "{html}");
68    }
69}