Motion for Angular that follows your state.
Start with one attribute. Coordinate enter, exit and state changes when your interface needs more. Native browser animations and Angular signals, with zero runtime dependencies.
npm install angular-movement- runtime deps
- 0
- native engine
- WAAPI
- zoneless ready
- SSR
Stable APIs, one attribute away
STATE → MOTION
Change the data. The interface follows.
Add, complete, expand and remove tasks. Every transition comes from a signal changing, not from imperative animation code.
- Rows enter, leave and reorder without index bookkeeping.
- Completing a task animates to a new state; nothing is recreated.
- Details stay mounted until their leave animation has finished.
Today
An interactive task list: add, complete, expand and remove tasks.
Built only from stable APIs: *movePresenceFor, *movePresence, [moveAnimation], moveWhileHover. Honours prefers-reduced-motion.
import { Component, signal } from '@angular/core';
import {
MoveAnimationDirective,
MoveEnterDirective,
MoveLeaveDirective,
MoveHoverDirective,
MovePresenceDirective,
MovePresenceForDirective,
} from 'angular-movement';
@Component({
selector: 'app-tasks',
imports: [
MovePresenceForDirective,
MovePresenceDirective,
MoveAnimationDirective,
MoveEnterDirective,
MoveLeaveDirective,
MoveHoverDirective,
],
template: `
<ul>
<li
*movePresenceFor="let task of tasks(); trackBy: byId"
[moveWhileHover]="{ y: [0, -2] }"
>
<div
[moveAnimation]="{
initial: { scale: 1 },
animate: { scale: task.done ? 0.985 : 1 },
duration: 200
}"
>
{{ task.title }}
</div>
<ng-container *movePresence="task.open">
<p moveEnter="fade-down" moveLeave="fade-up">Details</p>
</ng-container>
</li>
</ul>
`,
})
export class Tasks {
tasks = signal([{ id: 1, title: 'Review PR', done: false, open: false }]);
byId = (_: number, task: { id: number }) => task.id;
}SEE IT MOVE / SCROLL THE STORY
Four things CSS alone makes awkward.
Each one is a stable API, running live. Scroll, or pick a tab.
Pressed 0×
Feedback while something is true: the pointer is over it, it is pressed. Touch gets press feedback, not a sticky hover.
<button moveWhileHover="lift" moveWhileTap="press">Save</button>Built for state. Here's why.
Angular already animates simple enter and leave. Movement exists for the part that is hard to coordinate by hand: motion that is driven by application state.
Not sure whether you need it? Read when CSS or Angular's native animations are enough.
Change a setting, see the motion, copy the code
This is the real moveEnter directive, not a recording. The snippet is generated from the same values you are editing.
fade-up
entered 1×
<div
moveEnter="fade-up"
moveDuration="500ms"
moveEasing="ease-out"
>
Billing summary
</div>What you can build
A short list of interface problems the library is good at. Hover a tile to see it, then open its live demo or the documentation.
Use the simplest tool that works
Movement is not a replacement for CSS or for Angular's own animate.enter / animate.leave. It adds value when motion has to react to state and be coordinated.
- Zero JavaScript, runs before hydration
- Best for state that already lives in a class or pseudo-class
- No coordination with element lifetime
- Built into Angular, nothing to install
- Applies CSS classes while a node enters or leaves
- Ideal when each element has its own self-contained enter/leave
- Reactive state-to-state transitions, variants and stagger
- Keyed-list presence, springs, scroll-linked and SVG motion
- Signals-based values, imperative MoveAnimator, SSR-safe
- element.animate() directly, maximal control
- You own cancellation, reduced motion and cleanup
- Fine for a single isolated effect
TEMPLATES / READY TO SHIP
Start from a template
Complete pages with motion already wired in. Open one, read the source, and keep what fits your product.
Product landing
Hero, feature grid, steps and a call to action, composed with Angular Movement, Volt UI components and Lumen icons. Copy the sections you need.
- Staggered entrances that respect reduced motion
- Hover and press feedback on every card
- Scroll-revealed sections, server-rendered first
Learn it the way you prefer
The same examples are reachable three ways, and each links to the others.
Read the guides Task-first documentation: install, animate on enter, react to state, keep things mounted while they leave. Searchable, with live playgrounds inline. Get started Experiment in the demos A full playground per directive: tune presets, timing and easing, replay the motion and copy valid Angular code. Explore demos Check the contract Every public directive, input, output and type, generated from the library source with its stability — stable, experimental or deprecated. Open the API reference
Questions worth asking first
Short answers, with the page that has the long one.
If the motion is a function of a class or a pseudo-class, or one element has its own enter and leave, CSS and Angular’s animate.enter / animate.leave are the right tools. Movement earns its place when motion follows state and has to be coordinated: presence, variants, stagger, scroll.
Choose the right tool →Yes. Every directive is a no-op on the server and starts after hydration, and nothing needs Zone.js. Because it runs after hydration, use CSS for an above-the-fold entrance that must paint immediately.
SSR and hydration →The operating system setting is honoured automatically: directives jump to the end state. provideMovement({ disabled }) and moveDisabled add an app-level and a per-element switch.
Reduced motion →Enter, leave, presence, variants, interactions, stagger, scroll, motion values and MoveAnimator are stable. Layout, drag, smooth scroll and the target/trigger pair are experimental and marked as such everywhere.
API overview and stability →Often the right answer is plain CSS. The migration guide classifies each trigger and shows reviewed recipes for the ones that benefit from Movement.
Migration guide →Ready to move?
Install the package, import one directive, and animate your Angular 21 or 22 application.
npm install angular-movement