Presence
Enter and exit animations for anything that mounts and unmounts. A preset class from navius-motion.css keys off the discrete state attributes, so a Dialog popup or a Collapsible panel animates with no JavaScript.
@* Any part with the state-attribute contract. No KeepMounted needed for exits. *@
<NaviusCollapsiblePanel class="motion-pop">
...
</NaviusCollapsiblePanel>Preset classes
Add one class. Every preset fades (so exits always clear cleanly) and enters to the element's natural state. Enters use a calmer spring; every exit uses the snappy spring, because exits should get out of the way faster than enters arrive.
| Class | Enters from | Spring in / out |
|---|---|---|
| .motion-fade | opacity 0 | Smooth / Snappy |
| .motion-fade-up | opacity 0, translateY(8px) | Smooth / Snappy |
| .motion-fade-down | opacity 0, translateY(-8px) | Smooth / Snappy |
| .motion-zoom | opacity 0, scale(0.95) | Default / Snappy |
| .motion-pop | opacity 0, scale(0.9) | Bouncy / Snappy |
| .motion-slide-up | opacity 0, translateY(24px) | Default / Snappy |
| .motion-slide-down | opacity 0, translateY(-24px) | Default / Snappy |
| .motion-slide-left | opacity 0, translateX(24px) | Default / Snappy |
| .motion-slide-right | opacity 0, translateX(-24px) | Default / Snappy |
Each preset also has an insert-only twin, .motion-enter-* (for example .motion-enter-fade-up), built on @starting-style. Those animate once when the element enters the DOM and need no state attributes at all; delay them with --navius-motion-delay.
The state contract
The presence classes read the same discrete attributes every Navius primitive part already emits. Nothing else couples the two: drop the class on the part and the primitive's own deferred-unmount timing drives the exit.
| Data attribute | Values |
|---|---|
| [data-open] | Present while open; the resting state the enter animates to |
| [data-closed] | Present while closed; carries the hidden state |
| [data-starting-style] | Present on the first committed frame after mount; the enter's from state |
| [data-ending-style] | Present while animating out; triggers the exit |
Splat helpers
For zero-wrapper usage, Motion returns attribute dictionaries to splat with @attributes. Blazor's duplicate-attribute rule is last wins, so splat these instead of a literal class, or merge manually.
| Member | Returns | Effect |
|---|---|---|
| Motion.Presence(Preset preset) | IReadOnlyDictionary<string, object> | The .motion-<preset> presence class. |
| Motion.Enter(Preset preset, double delayMs = 0) | IReadOnlyDictionary<string, object> | The .motion-enter-<preset> class, with an optional delay variable. |
The runtime path
When you need interruption handling (rapid open/close on an overlay), use the WAAPI tier. MotionPrograms.Presence bakes a preset's enter and exit springs in C#; CreatePresenceMotionAsync attaches an observer that runs them from a live computed snapshot, so an interrupted enter hands over to the exit continuously. It cooperates with the presence machine's deferred unmount through getAnimations() with no extra coupling.
@inject IJSRuntime JS
var interop = new MotionJsInterop(JS);
var options = MotionPrograms.Presence(MotionPresets.Get(Preset.Pop));
// Override either phase's spring if you like:
// MotionPrograms.Presence(MotionPresets.Get(Preset.Pop), exitSpring: Spring.Smooth);
_presence = await interop.CreatePresenceMotionAsync(_element, options);
// Later: await _presence.DisposeAsync();MotionJsInterop
Bridge to navius-motion.js. CreatePresenceMotionAsync returns a PresenceMotion; dispose it to disconnect the observer and cancel its animations.
| Prop | Type | Default |
|---|---|---|
| CreatePresenceMotionAsync(ElementReference element, PresenceMotionOptions options) | Task<PresenceMotion> | - |
| MotionPrograms.Presence(MotionPreset preset, Spring? enterSpring = null, Spring? exitSpring = null) | PresenceMotionOptions | - |
PresenceMotionOptions
Enter plays when data-starting-style appears or is removed; exit when data-ending-style appears. Build it from a preset with MotionPrograms.Presence.
| Prop | Type | Default |
|---|---|---|
| Enter | MotionPhase | - |
| Exit | MotionPhase | - |
| ReduceMotion | string | "user" |
MotionPhase
One presence phase: the keyframes plus the baked timing to play them with.
| Prop | Type | Default |
|---|---|---|
| Keyframes | MotionFrame[] | - |
| DurationMs | double | - |
| Easing | string | - |