yggdrasil/components/
empty_state.rs1use dioxus::prelude::*;
4
5use crate::components::ui::BTN_PRIMARY;
6
7const EMPTY_STATE_IMAGES: &[&str] = &[
8 "/images/empty-state/dog-camera.webp",
9 "/images/empty-state/dog-wind-chime.webp",
10 "/images/empty-state/dog-delivery.webp",
11 "/images/empty-state/dog-pajamas.webp",
12 "/images/empty-state/dog-watermelon.webp",
13 "/images/empty-state/dog-heart.webp",
14 "/images/empty-state/dog-head-pat.webp",
15 "/images/empty-state/dog-mirror.webp",
16 "/images/empty-state/dog-chopsticks.webp",
17 "/images/empty-state/dog-grass.webp",
18 "/images/empty-state/dog-polaroid.webp",
19 "/images/empty-state/dog-autumn-leaf.webp",
20 "/images/empty-state/dog-laptop.webp",
21 "/images/empty-state/dog-heartbeat.webp",
22 "/images/empty-state/dog-travel.webp",
23 "/images/empty-state/dog-ring.webp",
24 "/images/empty-state/dog-hug.webp",
25 "/images/empty-state/dog-sparklers.webp",
26];
27
28#[derive(Props, Clone, PartialEq)]
30pub struct EmptyStateAction {
31 #[props(into)]
32 pub label: String,
33 pub onclick: EventHandler<()>,
34}
35
36#[component]
38pub fn EmptyState(
39 #[props(into, default = "还没有文章".to_string())] title: String,
40 #[props(into, default = String::new())] description: String,
41 #[props(into, default = String::new())]
43 image: String,
44 #[props(default)] action: Option<EmptyStateAction>,
45) -> Element {
46 let selected = use_signal(|| 0_usize);
48 use_effect(move || {
49 #[cfg(target_arch = "wasm32")]
50 {
51 let mut selected = selected;
52 selected.set((js_sys::Math::random() * EMPTY_STATE_IMAGES.len() as f64) as usize);
53 }
54 });
55 let src = if image.is_empty() {
56 EMPTY_STATE_IMAGES[selected()]
57 } else {
58 &image
59 };
60
61 rsx! {
62 section { class: "empty-state",
63 div { class: "empty-state-art",
64 img { src: "{src}", alt: "", width: "192", height: "192", draggable: "false" }
65 }
66 span { class: "empty-state-kicker", "YGGDRASIL / 一处留白" }
67 h2 { "{title}" }
68 if !description.is_empty() {
69 p { class: "empty-state-description", "{description}" }
70 }
71 if let Some(act) = action {
72 button {
73 class: "{BTN_PRIMARY} empty-state-action",
74 r#type: "button",
75 onclick: move |_| act.onclick.call(()),
76 "{act.label}"
77 }
78 }
79 }
80 }
81}