Typed, interruptible animation for Dioxus. Animate a value, read it in your component, and let springs or tweens carry it to the next destination.
Documentation & playground · Examples · Release notes
This branch targets Dioxus 0.7.10 and Rust 1.89+. It contains breaking changes for the next release. Examples below describe this branch; use the published API documentation when depending on the crates.io release.
For a web app:
[dependencies]
dioxus = { version = "0.7.10", features = ["web"] }
dioxus-motion = { git = "https://github.com/wheregmis/dioxus-motion", branch = "main", default-features = false, features = ["web"] }Commit Cargo.lock to pin the Git revision. For desktop apps, use the desktop feature. Add transitions for animated router outlets. The animation core is also available without the default features.
use dioxus::prelude::*;
use dioxus_motion::prelude::*;
#[component]
fn MovingButton() -> Element {
let mut x = use_motion(0.0_f32)?;
let mut forward = use_signal(|| false);
let mut error = use_signal(|| None::<String>);
rsx! {
button {
onclick: move |_| {
let target = if forward() { 0.0 } else { 160.0 };
match x.animate_to(target, AnimationConfig::spring(Spring::default())) {
Ok(()) => { forward.toggle(); error.set(None); }
Err(problem) => error.set(Some(problem.to_string())),
}
},
style: "transform: translateX({x.get_value()}px)",
"Move me"
}
if let Some(problem) = error() { p { role: "alert", "{problem}" } }
}
}Retargeting a running spring starts from its current value and momentum. Reading get_value() subscribes the component to value changes; reading is_running() subscribes to playback changes.
The live quick start is compiled as part of the documentation app, and the docs display that same file.
| Need | API | Guide |
|---|---|---|
| Natural motion with momentum | AnimationConfig::spring(Spring { stiffness, damping, mass }) |
Values & springs |
| A fixed duration | AnimationConfig::tween(Duration) |
Loops & sequences |
| Ordered steps or explicit keyframes | AnimationSequence, KeyframeAnimation |
Sequences |
| Typed CSS properties | MotionStyle, motion_style! |
Animating CSS |
| Enter, exit, and layout coordination | AnimatePresence, use_presence_motion, use_presence_style |
Presence |
| Route changes | MotionTransitions, AnimatedOutlet |
Transitions |
| Your own data | Animatable |
Custom types |
Construction, hooks, animation setup, velocity changes, and frame updates return typed errors. Handle AnimationError at the boundary where you accept user input or configure motion.
Presence hooks validate initial, animate, and exit values and their transitions before registering work. PresenceConfig::validate() also checks the optional layout transition. Spring entry must support re-entry from the exit state; use a tween when those states use incompatible CSS units.
- Initial values, targets, velocities, and frame results must be finite.
Animatable::is_finitechecks every numeric component of a custom type. - Invalid setup preserves existing playback. A failed frame stops playback and retains the last valid value.
- CSS springs require compatible units and complex shapes for shared properties. Use a tween for changing units or discrete values. Invalid spring transitions return
IncompatibleSpringValuesbefore playback changes. set_velocitytakes the animated value’s type and requires an active spring. A scalar spring acceptsf32; a transform spring accepts aTransformvelocity.- Custom values implement
Clone + PartialEq + Animatable. Exact equality controls reactive updates; epsilon controls spring convergence. - Read-only motion selectors do not expose mutable animation state. Use the checked setters to change values or playback.
See CHANGELOG.md for the migration details, including the removed closure pool API.
Springs use a closed-form step with cached coefficients. Keyframe lookup uses a short scan for small tracks and binary search for larger tracks. Motion signals notify only when their observed value changes.
The repository includes numerical stress tests, frame-error regressions, mutation tests, and a real-browser timing/cancellation harness. Benchmarks are measurements for a particular build and machine; they are not a guarantee of application frame rate.
cargo test --workspace --locked
cargo clippy --workspace --all-targets --locked -- -D warnings
cargo test --release test_motion_update_cpu_usage -- --ignored --nocaptureFor documentation development and the GitHub Pages deployment, see docs/README.md.
Keep examples aligned with the checked API, test changes at their observable boundary, and prefer a small implementation that is easy to maintain. Open an issue or pull request with a reproducible case.
MIT.