diff --git a/frontend/src/components/demos/demo_shimmer.rs b/frontend/src/components/demos/demo_shimmer.rs new file mode 100644 index 0000000..3fcff19 --- /dev/null +++ b/frontend/src/components/demos/demo_shimmer.rs @@ -0,0 +1,91 @@ +use leptos::prelude::*; +use leptos::task::spawn_local; +use serde::{Deserialize, Serialize}; + +use crate::components::ui::button::{Button, ButtonVariant}; +use crate::components::ui::card::{Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle}; +use crate::components::ui::shimmer::Shimmer; + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct CardData { + pub title: String, + pub description: String, +} + +/// Simulates a database fetch with 1 second delay +#[server] +pub async fn fetch_card_data() -> Result { + // Simulate network/database latency (only on server) + #[cfg(feature = "ssr")] + tokio::time::sleep(std::time::Duration::from_secs(1)).await; + + Ok(CardData { + title: "Fetched Title".to_string(), + description: "This content was fetched from the server after a 1 second simulated delay. The shimmer effect automatically showed during the loading period.".to_string(), + }) +} + +#[component] +pub fn DemoShimmer() -> impl IntoView { + // Loading state + let loading = RwSignal::new(false); + + // Store fetched data + let card_data = RwSignal::new(None::); + + // Fetch handler using spawn_local for reliable repeated calls + let on_fetch = move |_| { + spawn_local(async move { + loading.set(true); + let result = fetch_card_data().await; + if let Ok(data) = result { + card_data.set(Some(data)); + } + loading.set(false); + }); + }; + + view! { +
+
+ + +
+ + + + + + {move || { + card_data.get().map(|data| data.title).unwrap_or_else(|| "Card Title".to_string()) + }} + + + + + + {move || { + card_data + .get() + .map(|data| data.description) + .unwrap_or_else(|| { + "Click 'Toggle Loading' for manual control, or 'Fetch Data' to simulate a real server call with 1 second delay." + .to_string() + }) + }} + + + + + + + + + +
+ } +} \ No newline at end of file diff --git a/frontend/src/components/torrent/details.rs b/frontend/src/components/torrent/details.rs index 2c49c04..ed754dd 100644 --- a/frontend/src/components/torrent/details.rs +++ b/frontend/src/components/torrent/details.rs @@ -132,22 +132,24 @@ fn InfoItem( #[component] fn DetailsShimmer() -> impl IntoView { view! { -
- {(0..8).map(|_| view! { -
- - + +
+ {(0..8).map(|_| view! { +
+
+
+
+ }).collect_view()} +
+
+
+
+
+
+
- }).collect_view()} -
- -
-
- - -
-
+ } } diff --git a/frontend/src/components/ui/shimmer.rs b/frontend/src/components/ui/shimmer.rs index a2d4af7..2b7e163 100644 --- a/frontend/src/components/ui/shimmer.rs +++ b/frontend/src/components/ui/shimmer.rs @@ -1,13 +1,52 @@ use leptos::prelude::*; -use tw_merge::tw_merge; +use tw_merge::*; + +use crate::components::hooks::use_random::use_random_id_for; #[component] pub fn Shimmer( - #[prop(optional, into)] class: String, + /// Controls shimmer visibility (works with any bool signal) + #[prop(into)] + loading: Signal, + + /// Color of the shimmer wave (default: "rgba(255,255,255,0.15)") + #[prop(into, optional)] + shimmer_color: Option, + + /// Background color of shimmer blocks (default: "rgba(255,255,255,0.08)") + #[prop(into, optional)] + background_color: Option, + + /// Animation duration in seconds (default: 1.5) + #[prop(optional)] + duration: Option, + + /// Fallback border-radius for text elements in px (default: 4) + #[prop(optional)] + fallback_border_radius: Option, + + /// Additional classes + #[prop(into, optional)] + class: String, + + /// Children to wrap + children: Children, ) -> impl IntoView { - let merged_class = tw_merge!( - "relative overflow-hidden bg-muted before:absolute before:inset-0 before:-translate-x-full before:animate-[shimmer_2s_infinite] before:bg-gradient-to-r before:from-transparent before:via-white/20 before:to-transparent dark:before:via-white/5", - class - ); - view! {
} -} + let shimmer_id = use_random_id_for("Shimmer"); + let merged_class = tw_merge!("relative", class); + + view! { +
+ {children()} +
+ } +} \ No newline at end of file