perf: refactor hold-to-action animation using CSS for silky-smooth performance
Some checks failed
Build MIPS Binary / build (push) Failing after 35s

This commit is contained in:
spinline
2026-02-13 13:32:40 +03:00
parent dd3b3f3504
commit dbbc722f50

View File

@@ -86,37 +86,23 @@ pub fn ContextMenuHoldAction(
#[prop(default = 1000)] hold_duration: u64, #[prop(default = 1000)] hold_duration: u64,
) -> impl IntoView { ) -> impl IntoView {
let is_holding = RwSignal::new(false); let is_holding = RwSignal::new(false);
let progress = RwSignal::new(0.0);
let on_mousedown = move |_| { let on_mousedown = move |_| {
is_holding.set(true); is_holding.set(true);
progress.set(0.0);
}; };
let on_mouseup = move |_| { let on_mouseup = move |_| {
is_holding.set(false); is_holding.set(false);
progress.set(0.0);
}; };
Effect::new(move |_| { Effect::new(move |_| {
if is_holding.get() { if is_holding.get() {
let start_time = js_sys::Date::now();
let duration = hold_duration as f64;
leptos::task::spawn_local(async move { leptos::task::spawn_local(async move {
while is_holding.get_untracked() { gloo_timers::future::TimeoutFuture::new(hold_duration as u32).await;
let now = js_sys::Date::now(); if is_holding.get_untracked() {
let elapsed = now - start_time;
let p = (elapsed / duration).min(1.0);
progress.set(p * 100.0);
if p >= 1.0 {
on_hold_complete.run(()); on_hold_complete.run(());
is_holding.set(false); is_holding.set(false);
close_context_menu(); close_context_menu();
break;
}
gloo_timers::future::TimeoutFuture::new(16).await; // ~60fps
} }
}); });
} }
@@ -128,8 +114,18 @@ pub fn ContextMenuHoldAction(
); );
view! { view! {
<style>
"@keyframes hold-progress {
from { width: 0%; }
to { width: 100%; }
}
.animate-hold {
animation: hold-progress var(--hold-duration) linear forwards;
}"
</style>
<div <div
class=class class=class
attr:style=format!("--hold-duration: {}ms", hold_duration)
on:mousedown=on_mousedown on:mousedown=on_mousedown
on:mouseup=on_mouseup on:mouseup=on_mouseup
on:mouseleave=on_mouseup on:mouseleave=on_mouseup
@@ -137,10 +133,10 @@ pub fn ContextMenuHoldAction(
on:touchend=move |_| on_mouseup(web_sys::MouseEvent::new("mouseup").unwrap()) on:touchend=move |_| on_mouseup(web_sys::MouseEvent::new("mouseup").unwrap())
> >
// Progress background // Progress background
<div <Show when=move || is_holding.get()>
class="absolute inset-y-0 left-0 bg-destructive/20 transition-all duration-75 ease-linear pointer-events-none" <div class="absolute inset-y-0 left-0 bg-destructive/20 pointer-events-none animate-hold" />
style=move || format!("width: {}%;", progress.get()) </Show>
/>
<span class="relative z-10 flex items-center gap-2 w-full"> <span class="relative z-10 flex items-center gap-2 w-full">
{children()} {children()}
</span> </span>