Skip to main content

autumn_plugin_motion/
lib.rs

1//! Motion animations for Autumn, with Maud + htmx ergonomics.
2//!
3//! Add [`MotionPlugin`] to the app, put [`motion_script()`] in the page, and
4//! animate declaratively:
5//!
6//! ```rust,no_run
7//! use autumn_plugin_motion::{Motion, MotionPlugin, motion_script};
8//! use autumn_web::prelude::*;
9//!
10//! #[get("/")]
11//! async fn index() -> Markup {
12//!     html! {
13//!         html {
14//!             head { (motion_script()) }
15//!             body {
16//!                 // Typed builder: wraps the markup in an animated div.
17//!                 (Motion::fade_up().delay(100).wrap(html! {
18//!                     h1 { "Hello" }
19//!                 }))
20//!                 // Or raw attributes on your own elements:
21//!                 p data-motion="fade" data-motion-delay="200" { "World" }
22//!             }
23//!         }
24//!     }
25//! }
26//!
27//! # async fn run() {
28//! autumn_web::app()
29//!     .plugin(MotionPlugin::new())
30//!     .routes(routes![index])
31//!     .run()
32//!     .await;
33//! # }
34//! ```
35//!
36//! The plugin vendors [Motion](https://motion.dev) 12.x (MIT) — no npm, no
37//! bundler — and installs it as an Autumn plugin asset bundle
38//! ([`MOTION_ASSETS`]), served from memory under `/static/_plugins/motion/`
39//! at content-hashed, immutably cached URLs with SRI hashes computed from the
40//! embedded bytes. The init script
41//! scans `[data-motion]` on load and re-scans on `htmx:afterSwap`, so every
42//! htmx partial animates declaratively too. `prefers-reduced-motion` is
43//! respected: no animations, content stays visible.
44//!
45//! # Limits
46//!
47//! - Motion+ (the paid motion.dev tier: `splitText`, `Cursor`, `Carousel`,
48//!   `Ticker`, `AnimateNumber`, …) is not included — only the MIT core.
49//! - The Motion version is pinned per plugin release (see
50//!   [`assets::MOTION_VERSION`]); upgrading Motion means upgrading the plugin.
51//! - Animations are enter/scroll effects on server-rendered HTML. There is no
52//!   layout-animation / shared-element support in the declarative layer.
53//! - Without JavaScript (or with reduced motion) everything renders
54//!   statically — by design.
55
56mod assets;
57mod motion;
58mod plugin;
59mod script;
60
61pub use assets::{
62    ASSETS_NAMESPACE, MOTION_ASSETS, MOTION_JS_INTEGRITY, MOTION_SOURCE, MOTION_VERSION,
63};
64pub use motion::{Ease, InViewAmount, Motion, Preset, RepeatType, StaggerFrom};
65pub use plugin::{MotionPlugin, PLUGIN_NAME};
66pub use script::{motion_script, motion_stylesheet};