Skip to content

Andersseen/angular-movement

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

100 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Angular Movement logo

Angular Movement

Animate Angular with a single attribute.

Declarative motion for Angular 21 β€” presets, spring physics, drag, scroll, parallax, presence orchestration & SVG path-drawing. SSR-safe. Zero @angular/animations. Standalone-ready.


CI npm version npm downloads bundle size Angular License: MIT PRs welcome

🌐 Live Demo Β Β·Β  πŸ“š Docs Β Β·Β  πŸ“¦ npm Β Β·Β  πŸ—ΊοΈ Roadmap

Angular Movement β€” animate Angular with a single attribute

Why Angular Movement?

UI animation in Angular tends to sprawl: enter/leave transitions rewritten per component, imperative logic tangled into templates, inconsistent timings across a team, and no clean way to orchestrate staggered lists or exit animations.

Angular Movement replaces that boilerplate with declarative directives and one global config, so motion stays consistent, composable, and SSR-safe. Playback runs on the browser's native Web Animations API (with an optional spring physics engine) β€” no @angular/animations setup required.

<h2 [move]="'fade-up'">Hello movement</h2>
<button [moveWhileHover]="{ scale: [1, 1.05] }">Hover me</button>

✨ Features

🎬 30+ presets fade, slide, zoom, flip, blur, bounce, pulse, spin, icon-draw/pulse/bounce
🧬 Custom keyframes full control when a preset isn't enough
πŸƒ Spring physics pre-computed spring keyframes via a dedicated engine
πŸ–±οΈ Interactions hover, tap, focus, in-view, scroll, parallax, drag
🎯 Advanced drag axis-lock, constraints, elasticity, momentum, snap-to-origin & snap points
πŸ‘» Presence let leave animations finish before the DOM node is removed
πŸͺœ Stagger coordinated, ordered list motion
✍️ SVG path drawing animate pathLength / pathOffset, WAAPI-powered
⏱️ Per-property transitions different duration / delay per animated property
πŸ”€ Motion values derive motion from Angular signals (moveValue, moveTransform, moveSpringValue)
πŸ–₯️ SSR-safe every browser API guarded; no-ops on the server
🧱 Standalone-ready tree-shakeable directives, no NgModule required

πŸš€ Quick start

npm install angular-movement
# or: pnpm add angular-movement Β· yarn add angular-movement

Peer dependencies: @angular/core ^21.2.0 Β· @angular/common ^21.2.0

1. Provide global defaults

import { ApplicationConfig } from '@angular/core';
import { provideMovement } from 'angular-movement';

export const appConfig: ApplicationConfig = {
  providers: [
    provideMovement({
      duration: 320,
      easing: 'cubic-bezier(0.16, 1, 0.3, 1)',
      delay: 0,
      disabled: false,
    }),
  ],
};

2. Import the directives and use them in templates

import { Component } from '@angular/core';
import { MOVEMENT_DIRECTIVES } from 'angular-movement';

@Component({
  selector: 'app-demo-card',
  standalone: true,
  imports: [...MOVEMENT_DIRECTIVES],
  template: `
    <h2 [move]="'fade-up'">Hello movement</h2>
    <button [moveWhileHover]="{ scale: [1, 1.05] }">Hover me</button>
  `,
})
export class DemoCardComponent {}

🧩 Pick the right primitive

Start with the smallest primitive that matches the job:

Level Reach for
Basic moveEnter, moveLeave, [move], moveInitial, moveAnimate, moveExit
Interactions moveWhileHover, moveWhileTap, moveFocus, moveInView
State moveVariants, moveTarget, moveTrigger
Orchestration movePresence, moveStagger
Scroll & layout moveScroll, moveParallax, moveLayout, moveSmoothScroll
Advanced pathLength, pathOffset, transition, spring, moveDrag

moveLeave plays only while a parent movePresence keeps the view alive during removal. A plain @if removes the element immediately, so there is no node left to animate.

πŸŽ›οΈ Explore the interactive playground

Every directive has a focused page with a live config panel and copy-paste HTML output.

Demo pages: Animate Β· Enter & Leave Β· Hover & Tap Β· In-View Β· Scroll & Parallax Β· Presence Β· Layout Β· Drag Β· Variants Β· Text Β· SVG Icons

πŸ“– Recipes

Motion-style API β€” initial / animate / exit
<ng-container *movePresence="isOpen">
  <article
    [moveInitial]="{ opacity: 0, y: 24 }"
    [moveAnimate]="{ opacity: 1, y: 0 }"
    [moveExit]="{ opacity: 0, y: -16 }"
    moveDuration="300"
  >
    Card
  </article>
</ng-container>

The object form [moveAnimation]="{ initial, animate, exit }" is also available for config-heavy cases.

Drag gestures β€” constraints, momentum, snap points
<div
  moveDrag="x"
  [moveDragConstraints]="{ left: -120, right: 120 }"
  [moveDragElastic]="0.35"
  [moveDragMomentum]="true"
  [moveDragSnapPoints]="[{ x: -120, y: 0 }, { x: 0, y: 0 }, { x: 120, y: 0 }]"
  (moveDragStart)="onDragStart($event)"
  (moveDragMove)="onDragMove($event)"
  (moveDragEnd)="onDragEnd($event)"
>
  Drag me
</div>

Use moveWhileTap for press feedback that returns on release; use moveDrag when the element should follow the pointer and keep a real position.

SVG path drawing & icon helpers

Animate pathLength from 0 to 1 to draw a stroke. The engine measures the element's total length and converts it to WAAPI-compatible strokeDasharray / strokeDashoffset keyframes.

<svg width="24" height="24" viewBox="0 0 24 24">
  <path
    [moveTarget]="animate()"
    [moveFrames]="{ pathLength: [0, 1], opacity: [0, 1] }"
    moveDuration="700"
    fill="none"
    stroke="currentColor"
    stroke-width="2"
    d="M4 12l4-4 4 4 8-8"
  />
</svg>

Helper functions build icon keyframes quickly:

import { movePathDraw, moveIconPulse } from 'angular-movement';
<svg [moveTarget]="animate()" movePreset="icon-bounce" moveDuration="500">
  <!-- icon paths -->
</svg>
Variants with per-property transitions

Declare target states like Framer Motion. When moveAnimate changes, keyframes are generated from the previous state to the next.

<div
  [moveVariants]="{
    idle: { scale: 1, rotate: 0 },
    active: { scale: 1.08, rotate: 4 }
  }"
  [moveAnimate]="isActive ? 'active' : 'idle'"
>
  Card
</div>

Override timing per property, and point moveExitVariant at the variant that plays before removal:

<ng-container *movePresence="isOpen">
  <aside
    [moveVariants]="{
      visible: { opacity: 1, x: 0 },
      hidden: { opacity: 0, x: 24 }
    }"
    moveAnimate="visible"
    moveExitVariant="hidden"
  >
    Panel
  </aside>
</ng-container>
Motion values driven by signals
import { computed, inject, Injector } from '@angular/core';
import { moveSpringValue, moveTransform, moveValue } from 'angular-movement';

const progress = moveValue(0);
const x = moveTransform(progress, [0, 1], [0, 120]);
const scale = moveSpringValue(moveTransform(progress, [0, 1], [0.9, 1]), {
  injector: inject(Injector),
});
const transform = computed(() => `translateX(${x()}px) scale(${scale()})`);

Scroll directives expose progress as a signal, so you can derive values without a manual scroll loop:

<section
  #scroll="moveScroll"
  [moveScroll]="{ opacity: [0, 1] }"
  [style.--progress]="scroll.progress()"
>
  Scroll-linked content
</section>

πŸ—οΈ Repository structure

This is a pnpm monorepo with two parts:

Path What
projects/movement The publishable npm library (angular-movement)
src Demo & documentation site β€” AnalogJS (Vite + SSR, zoneless)

The demo site imports the library via a Vite path alias, so library changes are reflected live without a build step.

pnpm dev            # run the demo site
pnpm test           # library unit tests (Vitest)
ng build movement   # build the library β†’ dist/movement
pnpm build          # build the demo site (client + SSR)

🚒 Deployment

The demo site deploys to Cloudflare Pages β€” a single source of truth for hosting.

Live at angular-movement.andersseen.dev.

🀝 Contributing

Contributions are welcome through issues and pull requests. When proposing changes, include a problem statement, any public-API impact, and tests or demo updates for new behavior.

πŸ“„ License

MIT Β© Andersseen

Built with Angular, AnalogJS & the Web Animations API.

About

🎬 Declarative motion for Angular β€” animate with a single attribute. Presets, spring physics, drag, scroll, parallax, presence orchestration & SVG path-drawing. SSR-safe, zero @angular/animations, standalone-ready.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages