yggdrasil/src/components/post_card.rs
xfy b6f41e74e7 feat: image thumbnail + lightbox viewer
- Add ImageViewer reusable component with thumbnail and click-to-zoom
- PostCover: load ?w=1200 thumbnail, click to view full-size
- PostCard: display cover thumbnail (?thumb=400x300) in list view
- PostContent: inline images load ?w=800 thumbnail, click to zoom
- Add lightbox overlay styles with fade-in animation
- Add zoom cursor and hover effect for zoomable images
- Extend web-sys features for DOM image/lightbox manipulation
2026-06-08 15:52:47 +08:00

60 lines
2.5 KiB
Rust

use dioxus::prelude::*;
use dioxus::router::components::Link;
use crate::components::image_viewer::ImageViewer;
use crate::models::post::Post;
use crate::router::Route;
#[component]
pub fn PostCard(post: Post) -> Element {
let post_slug = post.slug.clone();
let date_str = post.formatted_date();
let has_cover = post.cover_image.is_some();
rsx! {
article {
class: "relative mb-6 p-6 bg-white dark:bg-[#2e2e33] rounded-lg border border-gray-200 dark:border-[#333] hover:-translate-y-0.5 hover:border-gray-300 dark:hover:border-gray-600 transition-all duration-250",
Link {
class: "block group",
to: Route::PostDetail { slug: post_slug },
if has_cover {
div {
class: "mb-4 -mx-6 -mt-6 overflow-hidden rounded-t-lg",
ImageViewer {
src: post.cover_image.clone().unwrap_or_default(),
thumb_params: "?thumb=400x300",
alt: post.title.clone(),
lazy_load: true,
}
}
}
h2 {
class: "text-2xl font-bold leading-tight text-gray-900 dark:text-[#dadadb] group-hover:opacity-80 transition-opacity",
"{post.title}"
}
div {
class: "mt-2 text-sm text-gray-500 dark:text-[#9b9c9d] leading-relaxed line-clamp-2",
"{post.summary.as_deref().unwrap_or_default()}"
}
div {
class: "mt-3 flex items-center gap-3 text-[13px] text-gray-400 dark:text-[#9b9c9d]",
span { "{date_str}" }
if !post.tags.is_empty() {
span { "·" }
for tag in post.tags.clone().into_iter() {
span {
Link {
class: "hover:text-gray-600 dark:hover:text-[#dadadb] transition-colors",
to: Route::TagDetail { tag: tag.clone() },
onclick: move |evt: dioxus::events::MouseEvent| evt.stop_propagation(),
"{tag}"
}
}
}
}
}
}
}
}
}