mirror of
https://github.com/adoyle0/thaw.git
synced 2025-03-13 22:19:49 -04:00
feat: add loading bar component
This commit is contained in:
parent
29068acd1a
commit
a05cda35d7
5 changed files with 208 additions and 40 deletions
|
@ -24,6 +24,14 @@ pub fn App() -> impl IntoView {
|
||||||
provide_context(theme);
|
provide_context(theme);
|
||||||
view! {
|
view! {
|
||||||
<Provider theme>
|
<Provider theme>
|
||||||
|
<TheRouter />
|
||||||
|
</Provider>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[component]
|
||||||
|
fn TheRouter() -> impl IntoView {
|
||||||
|
view! {
|
||||||
<Router base="/thaw">
|
<Router base="/thaw">
|
||||||
<Routes base="/thaw".to_string()>
|
<Routes base="/thaw".to_string()>
|
||||||
<Route path="/" view=Home/>
|
<Route path="/" view=Home/>
|
||||||
|
@ -64,7 +72,6 @@ pub fn App() -> impl IntoView {
|
||||||
<Route path="/mobile/toast" view=ToastDemoPage/>
|
<Route path="/mobile/toast" view=ToastDemoPage/>
|
||||||
</Routes>
|
</Routes>
|
||||||
</Router>
|
</Router>
|
||||||
</Provider>
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@ mod image;
|
||||||
mod input;
|
mod input;
|
||||||
mod input_number;
|
mod input_number;
|
||||||
mod layout;
|
mod layout;
|
||||||
|
mod loading_bar;
|
||||||
mod menu;
|
mod menu;
|
||||||
mod message;
|
mod message;
|
||||||
pub mod mobile;
|
pub mod mobile;
|
||||||
|
@ -53,6 +54,7 @@ pub use image::*;
|
||||||
pub use input::*;
|
pub use input::*;
|
||||||
pub use input_number::*;
|
pub use input_number::*;
|
||||||
pub use layout::*;
|
pub use layout::*;
|
||||||
|
pub use loading_bar::*;
|
||||||
pub use menu::*;
|
pub use menu::*;
|
||||||
pub use message::*;
|
pub use message::*;
|
||||||
pub use modal::*;
|
pub use modal::*;
|
||||||
|
|
11
src/loading_bar/loading-bar.css
Normal file
11
src/loading_bar/loading-bar.css
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
.thaw-loading-bar-container {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
z-index: 1000;
|
||||||
|
}
|
||||||
|
.thaw-loading-bar {
|
||||||
|
height: 2px;
|
||||||
|
max-width: 0;
|
||||||
|
}
|
46
src/loading_bar/loading_bar_provider.rs
Normal file
46
src/loading_bar/loading_bar_provider.rs
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
use super::{LoadingBar, LoadingBarRef};
|
||||||
|
use crate::{teleport::Teleport, utils::ComponentRef};
|
||||||
|
use leptos::*;
|
||||||
|
|
||||||
|
#[component]
|
||||||
|
pub fn LoadingBarProvider(children: Children) -> impl IntoView {
|
||||||
|
let loading_bar_ref = ComponentRef::<LoadingBarRef>::default();
|
||||||
|
provide_context(LoadingBarInjection { loading_bar_ref });
|
||||||
|
|
||||||
|
view! {
|
||||||
|
{children()}
|
||||||
|
<Teleport>
|
||||||
|
<LoadingBar comp_ref=loading_bar_ref/>
|
||||||
|
</Teleport>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct LoadingBarInjection {
|
||||||
|
loading_bar_ref: ComponentRef<LoadingBarRef>,
|
||||||
|
}
|
||||||
|
impl Copy for LoadingBarInjection {}
|
||||||
|
|
||||||
|
impl LoadingBarInjection {
|
||||||
|
pub fn start(&self) {
|
||||||
|
if let Some(loading_bar_ref) = self.loading_bar_ref.get_untracked() {
|
||||||
|
loading_bar_ref.start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn finish(&self) {
|
||||||
|
if let Some(loading_bar_ref) = self.loading_bar_ref.get_untracked() {
|
||||||
|
loading_bar_ref.finish();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn error(&self) {
|
||||||
|
if let Some(loading_bar_ref) = self.loading_bar_ref.get_untracked() {
|
||||||
|
loading_bar_ref.error();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn use_loading_bar() -> LoadingBarInjection {
|
||||||
|
expect_context::<LoadingBarInjection>()
|
||||||
|
}
|
102
src/loading_bar/mod.rs
Normal file
102
src/loading_bar/mod.rs
Normal file
|
@ -0,0 +1,102 @@
|
||||||
|
mod loading_bar_provider;
|
||||||
|
|
||||||
|
use crate::{mount_style, use_theme, utils::ComponentRef, Theme};
|
||||||
|
use leptos::*;
|
||||||
|
pub use loading_bar_provider::{use_loading_bar, LoadingBarProvider};
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct LoadingBarRef {
|
||||||
|
start: Callback<()>,
|
||||||
|
finish: Callback<()>,
|
||||||
|
error: Callback<()>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LoadingBarRef {
|
||||||
|
pub fn start(&self) {
|
||||||
|
self.start.call(());
|
||||||
|
}
|
||||||
|
pub fn finish(&self) {
|
||||||
|
self.finish.call(());
|
||||||
|
}
|
||||||
|
pub fn error(&self) {
|
||||||
|
self.error.call(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[component]
|
||||||
|
pub fn LoadingBar(#[prop(optional)] comp_ref: ComponentRef<LoadingBarRef>) -> impl IntoView {
|
||||||
|
mount_style("loading-bar", include_str!("./loading-bar.css"));
|
||||||
|
let theme = use_theme(Theme::light);
|
||||||
|
let css_vars = create_memo(move |_| {
|
||||||
|
let mut css_vars = String::new();
|
||||||
|
theme.with(|theme| {
|
||||||
|
css_vars.push_str(&format!(
|
||||||
|
"--thaw-background-color: {};",
|
||||||
|
theme.common.color_success
|
||||||
|
));
|
||||||
|
css_vars.push_str(&format!(
|
||||||
|
"--thaw-background-color-error: {};",
|
||||||
|
theme.common.color_error
|
||||||
|
));
|
||||||
|
});
|
||||||
|
css_vars
|
||||||
|
});
|
||||||
|
let loading_bar_ref = create_node_ref::<html::Div>();
|
||||||
|
let loading = create_rw_signal(false);
|
||||||
|
|
||||||
|
let start = Callback::new(move |_| {
|
||||||
|
loading.set(true);
|
||||||
|
if let Some(loading_bar_ref) = loading_bar_ref.get_untracked() {
|
||||||
|
let loading_bar_ref = loading_bar_ref
|
||||||
|
.style("background-color", "var(--thaw-background-color)")
|
||||||
|
.style("transition", "none")
|
||||||
|
.style("max-width", "0");
|
||||||
|
_ = loading_bar_ref.offset_width();
|
||||||
|
loading_bar_ref
|
||||||
|
.style("transition", "max-width 4s linear")
|
||||||
|
.style("max-width", "80%");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
let finish = Callback::new(move |_| {
|
||||||
|
if let Some(loading_bar_ref) = loading_bar_ref.get_untracked() {
|
||||||
|
let loading_bar_ref = loading_bar_ref
|
||||||
|
.style("background-color", "var(--thaw-background-color)")
|
||||||
|
.style("transition", "max-width 0.5s linear")
|
||||||
|
.style("max-width", "1000%");
|
||||||
|
loading_bar_ref.on(ev::transitionend, move |_| {
|
||||||
|
loading.set(false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
let error = Callback::new(move |_| {
|
||||||
|
if let Some(loading_bar_ref) = loading_bar_ref.get_untracked() {
|
||||||
|
if !loading.get() {
|
||||||
|
loading.set(true);
|
||||||
|
let loading_bar_ref = loading_bar_ref.clone();
|
||||||
|
let loading_bar_ref = loading_bar_ref
|
||||||
|
.style("transition", "none")
|
||||||
|
.style("max-width", "0");
|
||||||
|
_ = loading_bar_ref.offset_width();
|
||||||
|
}
|
||||||
|
let loading_bar_ref = loading_bar_ref
|
||||||
|
.style("background-color", "var(--thaw-background-color-error)")
|
||||||
|
.style("transition", "max-width 0.5s linear")
|
||||||
|
.style("max-width", "100%");
|
||||||
|
loading_bar_ref.on(ev::transitionend, move |_| {
|
||||||
|
loading.set(false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
comp_ref.load(LoadingBarRef {
|
||||||
|
start,
|
||||||
|
finish,
|
||||||
|
error,
|
||||||
|
});
|
||||||
|
view! {
|
||||||
|
<div class="thaw-loading-bar-container">
|
||||||
|
<div class="thaw-loading-bar" ref=loading_bar_ref style=move || css_vars.get()>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue