dioxus-transition
🎬 Seamless enter/leave transitions for Dioxus, inspired by Vue's <Transition> — declarative, built-in, composable.
dioxus-transition gives you a fully reactive <Transition> component: wrap the thing you're conditionally rendering and it animates in when it enters the DOM and out when it leaves, instead of just blinking into (and out of) existence.
🖤 Features
Drop-in
<Transition>— Wrap a conditionally-rendered element and it eases in and out — no more elements popping into existence like nothing happenedVue's mental model, Dioxus' reactivity — If you've used Vue's
<Transition>you already know the shape of this; under the hood it's signals all the way downBatteries included —
fadeandblurship in the box; don't like them?default-features = falseand roll your own 🧘A transition is just two CSS classes — Pick any
kind, provide a-hiddenand an-activatingclass, and you're off — no DSL to learnSSR-aware — Flip on the
ssrfeature for fullstack apps and it won't touch the DOM during server-side rendering
Table of Contents
⸻
📦 Installation
cargo
Add it with cargo add:
cargo add dioxus-transitionor drop it into your Cargo.toml by hand:
[dependencies]
dioxus-transition = "0.3"The built-in fade / blur stylesheet is injected by default. If you'd rather bring your own styles and skip the built-ins entirely, opt out:
[dependencies]
dioxus-transition = { version = "0.3", default-features = false }The latest version targets Dioxus 0.7 — see the compatibility table for the version mapping.
Fullstack apps
For fullstack (SSR) apps, enable the crate's ssr feature on the server so it knows not to perform DOM operations while server-side rendering:
[features]
server = ["dioxus/server", "dioxus-transition/ssr"]⸻
🧪 Usage
Quick example
Toggle a signal, wrap the conditional element in <Transition>, and let it animate:
use dioxus::prelude::*;
use dioxus_transition::prelude::*;
fn main() {
dioxus::launch(App);
}
#[component]
fn App() -> Element {
let mut visible = use_signal(bool::default);
rsx! {
div {
button {
onclick: move |_| visible.set(!visible()),
"Toggle"
}
Transition {
id: "square",
kind: "fade", // try "blur", or define your own
duration: 300,
if visible() {
div {
id: "square",
display: "block",
width: "200px",
height: "200px",
background: "red",
}
}
}
}
}
}The one thing worth calling out: the id you give <Transition> has to match the id of the element you're actually animating ("square" in both places above) — that's the node it reaches for in the DOM.
How it works
The <Transition> component watches whether its children are really there or have collapsed to a placeholder (<!--placeholder-->), and drives the animation off that:
On entrance it injects
*-transition-hidden, then on the next animation frame swaps in*-transition-activatingto animate inOn exit it runs the same animation in reverse and cleans up once the duration's elapsed
Two classes do all the work — <kind>-transition-hidden for the resting/hidden state and <kind>-transition-activating for the visible one — so a "transition" is really just a pair of CSS classes you control.
Props
| Prop | Type | Required | What it does |
|---|---|---|---|
id | String | Yes | The id of the element within the tree to animate (must match the rendered node) |
kind | String | Yes | The animation class prefix — a built-in (fade, blur) or your own |
duration | u32 | Yes | Animation duration, in milliseconds |
ignore_first | bool | No | Skip the entrance animation on first mount (default false). Handy when the element is present by default and you don't want it animating in on load |
Built-in styles
Enabled by default (builtins feature) and injected for you:
/* fade */
.fade-transition-hidden {
opacity: 0;
}
.fade-transition-activating {
opacity: 1;
}
/* blur */
.blur-transition-hidden {
backdrop-filter: brightness(1) blur(0);
}
.blur-transition-activating {
backdrop-filter: brightness(0.375) blur(2px);
}Don't like them? Set default-features = false and roll your own 🧘
Custom transitions
A kind is just a CSS class prefix, so use whatever name you like — all that matters is you provide these two classes:
.<kind>-transition-hidden— the hidden state.<kind>-transition-activating— the visible state
That's the whole contract. Define slide, zoom, whatever and pass it as kind.
⸻
🛠️ Compatibility
| Dioxus version | dioxus-transition version |
|---|---|
0.7 | 0.3 |
0.6 | 0.2 |
⸻
📁 Repo & Contributions
🛠️ Repo: https://github.com/dsplce-co/dioxus-transition 📦 Crate: https://crates.io/crates/dioxus-transition
Contributions, issues, ideas? Hit us up — let's make transitions in Dioxus delightful 🖤
⸻
📄 License
MIT or Apache-2.0, at your option.