Skip to content

Motion

Animated field decorators. Assign a value and the transition plays automatically — no imperative API needed.

sh
npm install @praxisjs/motion
sh
pnpm add @praxisjs/motion
sh
yarn add @praxisjs/motion
sh
bun add @praxisjs/motion

@Tween(options?)

Animates a numeric field from its current value to any new assignment using a duration-based tween.

tsx
import { Tween } from '@praxisjs/motion'

@Component()
class ProgressBar extends StatefulComponent {
  @Tween({ duration: 600, easing: 'easeOut' })
  progress = 0

  load() {
    this.progress = 100  // smoothly animates to 100
  }

  render() {
    return (
      <div
        class="bar"
        style={() => ({ width: `${this.progress}%` })}
      />
    )
  }
}

Reading the field returns the current interpolated value. Assigning starts a new animation from where it currently is.

OptionTypeDefaultDescription
durationnumber300Animation duration in ms
easingEasing'easeOut'Easing function or name
delaynumber0Delay before starting in ms

@Spring(options?)

Physics-based spring animation. Assigning a value lets the field settle naturally with momentum and overshoot.

tsx
import { Spring } from '@praxisjs/motion'

@Component()
class DragHandle extends StatefulComponent {
  @Spring({ stiffness: 0.2, damping: 0.7 })
  x = 0

  @Spring()
  y = 0

  onPointerMove(e: PointerEvent) {
    this.x = e.clientX
    this.y = e.clientY
  }

  render() {
    return (
      <div
        class="handle"
        style={() => ({ transform: `translate(${this.x}px, ${this.y}px)` })}
        onPointermove={(e) => this.onPointerMove(e)}
      />
    )
  }
}
OptionTypeDefaultDescription
stiffnessnumber0.15Spring strength — higher = snappier. Must be greater than 0.
dampingnumber0.8Resistance — lower = more bounce
massnumber1Object mass — higher = more inertia
precisionnumber0.001Settlement threshold

Validation

stiffness must be greater than 0. Passing 0 or a negative value throws an error.


Easings

Available easing names for @Tween:

ts
'linear' | 'easeIn' | 'easeOut' | 'easeInOut' | 'easeInCubic' | 'bounce' | 'elastic'

Passing an unrecognised name throws an error listing the valid options.

Custom easing: pass any (t: number) => number function where t is in [0, 1]:

ts
@Tween({ easing: (t) => t * t * t, duration: 400 })
scale = 1

Released under the MIT License.