or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

actions.mdcompiler.mdcore-runtime.mdeasing-functions.mdindex.mdlist-animations.mdmotion-animation.mdstore-management.mdtransitions.md
tile.json

motion-animation.mddocs/

Motion and Animation

Physics-based animations and smooth transitions between state values with spring and tween effects.

Capabilities

Spring Animation

Create stores with spring-based physics animations that simulate natural motion with bounce and elasticity.

/**
 * Creates a store whose value is animated with spring physics
 * @param value - Initial value
 * @param opts - Spring configuration options
 * @returns Spring store with physics-based animation
 */
function spring<T = any>(value?: T, opts?: SpringOpts): Spring<T>;

interface Spring<T> extends Readable<T> {
  /** Set new target value with optional animation options */
  set: (new_value: T, opts?: SpringUpdateOpts) => Promise<void>;
  /** Update value using callback with optional animation options */
  update: (fn: Updater<T>, opts?: SpringUpdateOpts) => Promise<void>;
  /** Spring stiffness (0-1, higher = more responsive) */
  stiffness: number;
  /** Spring damping (0-1, higher = less oscillation) */
  damping: number;
  /** Animation precision threshold */
  precision: number;
}

interface SpringOpts {
  /** Stiffness controls responsiveness (default: 0.15) */
  stiffness?: number;
  /** Damping controls oscillation (default: 0.8) */
  damping?: number;
  /** Precision threshold for stopping animation (default: 0.01) */
  precision?: number;
}

interface SpringUpdateOpts {
  /** Hard transition - skip animation */
  hard?: boolean;
  /** Soft transition - gradual mass recovery */
  soft?: string | number | boolean;
}

type Updater<T> = (target_value: T, value: T) => T;

Usage Examples:

import { spring } from "svelte/motion";

// Basic spring store
const coords = spring({ x: 50, y: 50 }, {
  stiffness: 0.1,
  damping: 0.25
});

// Animate to new position
coords.set({ x: 100, y: 200 });

// Update with callback
coords.update((target, current) => ({
  x: target.x + 10,
  y: target.y + 10
}));

// Responsive spring for UI elements
const scale = spring(1, {
  stiffness: 0.3,
  damping: 0.6
});

// Mouse hover effects
function handleMouseEnter() {
  scale.set(1.1);
}

function handleMouseLeave() {
  scale.set(1);
}

// Hard vs soft transitions
const position = spring({ x: 0, y: 0 });

// Hard transition (no animation)
position.set({ x: 100, y: 100 }, { hard: true });

// Soft transition (gradual acceleration)
position.set({ x: 200, y: 200 }, { soft: true });

Tween Animation

Create stores with smooth, time-based transitions between values using easing functions.

/**
 * Creates a store that provides smooth transitions between state values over time
 * @param value - Initial value
 * @param defaults - Default tween options
 * @returns Tweened store with time-based animation
 */
function tweened<T>(value?: T, defaults?: TweenedOptions<T>): Tweened<T>;

interface Tweened<T> extends Readable<T> {
  /** Set new value with optional tween options */
  set(value: T, opts?: TweenedOptions<T>): Promise<void>;
  /** Update value using callback with optional tween options */
  update(updater: Updater<T>, opts?: TweenedOptions<T>): Promise<void>;
}

interface TweenedOptions<T> {
  /** Delay before animation starts (ms) */
  delay?: number;
  /** Animation duration (ms) or function */
  duration?: number | ((from: T, to: T) => number);
  /** Easing function */
  easing?: (t: number) => number;
  /** Custom interpolation function */
  interpolate?: (a: T, b: T) => (t: number) => T;
}

type Updater<T> = (value: T) => T;

Usage Examples:

import { tweened } from "svelte/motion";
import { cubicOut } from "svelte/easing";

// Basic tweened store
const progress = tweened(0, {
  duration: 400,
  easing: cubicOut
});

// Animate progress bar
progress.set(75);

// Dynamic duration based on distance
const position = tweened(0, {
  duration: (from, to) => Math.abs(to - from) * 10,
  easing: cubicOut
});

// Color transitions
const color = tweened([255, 0, 0], {
  duration: 800,
  interpolate: (from, to) => (t) => [
    Math.round(from[0] + (to[0] - from[0]) * t),
    Math.round(from[1] + (to[1] - from[1]) * t),
    Math.round(from[2] + (to[2] - from[2]) * t)
  ]
});

color.set([0, 255, 0]); // Animate from red to green

// Text size animation
const fontSize = tweened(16, {
  duration: 300,
  easing: cubicOut
});

// Smooth number counting
const counter = tweened(0, { duration: 2000 });
counter.set(1000); // Count up to 1000 over 2 seconds

// Promise-based animation chaining
async function animateSequence() {
  await progress.set(25);
  await progress.set(50);
  await progress.set(100);
  console.log('Animation sequence complete');
}

Custom Interpolation

Advanced usage with custom interpolation functions for complex data types.

Object Interpolation:

import { tweened } from "svelte/motion";

const objectStore = tweened({ x: 0, y: 0, opacity: 1 }, {
  interpolate: (from, to) => (t) => ({
    x: from.x + (to.x - from.x) * t,
    y: from.y + (to.y - from.y) * t,
    opacity: from.opacity + (to.opacity - from.opacity) * t
  })
});

objectStore.set({ x: 100, y: 200, opacity: 0.5 });

Date Interpolation:

import { tweened } from "svelte/motion";

const dateStore = tweened(new Date(), {
  interpolate: (from, to) => (t) => {
    const fromTime = from.getTime();
    const toTime = to.getTime();
    return new Date(fromTime + (toTime - fromTime) * t);
  }
});

dateStore.set(new Date(Date.now() + 7 * 24 * 60 * 60 * 1000)); // Week from now

Animation Patterns

Common patterns for using motion stores in Svelte applications.

Coordinated Animations:

import { spring } from "svelte/motion";

const mainPosition = spring({ x: 0, y: 0 });
const shadowPosition = spring({ x: 0, y: 0 }, {
  stiffness: 0.05,
  damping: 0.9
});

// Main element moves immediately, shadow follows with delay
function moveTo(x, y) {
  mainPosition.set({ x, y });
  setTimeout(() => shadowPosition.set({ x, y }), 100);
}

Gesture-based Animation:

import { spring } from "svelte/motion";

const dragPosition = spring({ x: 0, y: 0 }, {
  stiffness: 0.2,
  damping: 0.4
});

let isDragging = false;

function handleMouseDown() {
  isDragging = true;
  // Stiffer spring while dragging
  dragPosition.stiffness = 1;
  dragPosition.damping = 1;
}

function handleMouseUp() {
  isDragging = false;
  // Bouncy spring when released
  dragPosition.stiffness = 0.1;
  dragPosition.damping = 0.3;
  // Snap back to origin
  dragPosition.set({ x: 0, y: 0 });
}

Loading Animations:

import { tweened } from "svelte/motion";
import { linear } from "svelte/easing";

const loadingProgress = tweened(0, {
  duration: 3000,
  easing: linear
});

async function simulateLoading() {
  await loadingProgress.set(30);  // Quick initial progress
  await loadingProgress.set(60);  // Slower middle phase
  await loadingProgress.set(100); // Final completion
}

Integration with Components

Using motion stores effectively in Svelte components:

// In a Svelte component
import { spring, tweened } from "svelte/motion";
import { cubicOut } from "svelte/easing";

const scale = spring(1);
const opacity = tweened(1);

function handleHover() {
  scale.set(1.1);
  opacity.set(0.8);
}

function handleLeave() {
  scale.set(1);
  opacity.set(1);
}
<!-- Template using reactive values -->
<div 
  style="transform: scale({$scale}); opacity: {$opacity}"
  on:mouseenter={handleHover}
  on:mouseleave={handleLeave}
>
  Animated element
</div>