From 8307e4ead6a08e23a0ffe13f718bc0faaffd4162 Mon Sep 17 00:00:00 2001 From: luoxiao Date: Thu, 19 Oct 2023 23:13:27 +0800 Subject: [PATCH] feat: add skeleton component --- src/lib.rs | 2 ++ src/skeleton/mod.rs | 47 +++++++++++++++++++++++++++++++++++++++ src/skeleton/skeleton.css | 24 ++++++++++++++++++++ src/skeleton/theme.rs | 23 +++++++++++++++++++ src/theme/mod.rs | 7 +++++- 5 files changed, 102 insertions(+), 1 deletion(-) create mode 100644 src/skeleton/mod.rs create mode 100644 src/skeleton/skeleton.css create mode 100644 src/skeleton/theme.rs diff --git a/src/lib.rs b/src/lib.rs index 47fcce6..da113f1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -22,6 +22,7 @@ mod modal; mod progress; mod radio; mod select; +mod skeleton; mod slider; mod space; mod table; @@ -53,6 +54,7 @@ pub use modal::*; pub use progress::*; pub use radio::*; pub use select::*; +pub use skeleton::*; pub use slider::*; pub use space::*; pub use table::*; diff --git a/src/skeleton/mod.rs b/src/skeleton/mod.rs new file mode 100644 index 0000000..2fc0a03 --- /dev/null +++ b/src/skeleton/mod.rs @@ -0,0 +1,47 @@ +mod theme; + +use crate::{theme::use_theme, Theme}; +use leptos::*; +pub use theme::SkeletionTheme; + +#[component] +pub fn Skeleton( + #[prop(default = MaybeSignal::Static(1), into)] repeat: MaybeSignal, + #[prop(optional, into)] text: MaybeSignal, + #[prop(optional, into)] width: Option>, + #[prop(optional, into)] height: Option>, +) -> impl IntoView { + let theme = use_theme(Theme::light); + let css_vars = create_memo(move |_| { + let mut css_vars = String::new(); + if text.get() { + css_vars.push_str("display: inline-block;"); + } + + if let Some(width) = width.as_ref() { + css_vars.push_str(&format!("width: {};", width.get())); + } + if let Some(height) = height.as_ref() { + css_vars.push_str(&format!("height: {};", height.get())); + } + + theme.with(|theme| { + css_vars.push_str(&format!( + "--background-color-start: {};", + theme.skeletion.background_color_start + )); + css_vars.push_str(&format!( + "--background-color-end: {};", + theme.skeletion.background_color_end + )); + }); + + css_vars + }); + (0..repeat.get()) + .into_iter() + .map(|_| { + view! {
} + }) + .collect_view() +} diff --git a/src/skeleton/skeleton.css b/src/skeleton/skeleton.css new file mode 100644 index 0000000..6effb96 --- /dev/null +++ b/src/skeleton/skeleton.css @@ -0,0 +1,24 @@ +.melt-skeleton { + width: 100%; + height: 1em; + background-color: var(--background-color-start); + + background: linear-gradient( + 90deg, + var(--background-color-start) 25%, + var(--background-color-end) 37%, + var(--background-color-start) 63% + ); + animation: meltSkeletonLoading 1.4s ease infinite; + background-size: 400% 100%; +} + +@keyframes meltSkeletonLoading { + from { + background-position: 100% 50%; + } + + to { + background-position: 0 50%; + } +} diff --git a/src/skeleton/theme.rs b/src/skeleton/theme.rs new file mode 100644 index 0000000..6b9f337 --- /dev/null +++ b/src/skeleton/theme.rs @@ -0,0 +1,23 @@ +use crate::theme::ThemeMethod; + +#[derive(Clone)] +pub struct SkeletionTheme { + pub background_color_start: String, + pub background_color_end: String, +} + +impl ThemeMethod for SkeletionTheme { + fn light() -> Self { + Self { + background_color_start: "#f2f2f2".into(), + background_color_end: "#e6e6e6".into(), + } + } + + fn dark() -> Self { + Self { + background_color_start: "rgba(255, 255, 255, 0.12)".into(), + background_color_end: "rgba(255, 255, 255, 0.18)".into(), + } + } +} diff --git a/src/theme/mod.rs b/src/theme/mod.rs index 8fb730e..cee4e16 100644 --- a/src/theme/mod.rs +++ b/src/theme/mod.rs @@ -2,7 +2,7 @@ mod common; use leptos::*; use self::common::CommonTheme; -use crate::{AlertTheme, ButtonTheme, InputTheme, MenuTheme, TableTheme}; +use crate::{AlertTheme, ButtonTheme, InputTheme, MenuTheme, SkeletionTheme, TableTheme}; pub trait ThemeMethod { fn light() -> Self; @@ -17,6 +17,7 @@ pub struct Theme { pub menu: MenuTheme, pub table: TableTheme, pub alert: AlertTheme, + pub skeletion: SkeletionTheme, } impl Theme { @@ -28,6 +29,7 @@ impl Theme { menu: MenuTheme::light(), table: TableTheme::light(), alert: AlertTheme::light(), + skeletion: SkeletionTheme::light(), } } pub fn dark() -> Self { @@ -38,6 +40,7 @@ impl Theme { menu: MenuTheme::dark(), table: TableTheme::dark(), alert: AlertTheme::dark(), + skeletion: SkeletionTheme::dark(), } } } @@ -51,6 +54,7 @@ impl ThemeMethod for Theme { menu: MenuTheme::light(), table: TableTheme::light(), alert: AlertTheme::light(), + skeletion: SkeletionTheme::light(), } } fn dark() -> Self { @@ -61,6 +65,7 @@ impl ThemeMethod for Theme { menu: MenuTheme::dark(), table: TableTheme::dark(), alert: AlertTheme::dark(), + skeletion: SkeletionTheme::dark(), } } }