Documentation Index
Fetch the complete documentation index at: https://docs.metabind.ai/llms.txt
Use this file to discover all available pages before exploring further.
Animation constructors create AnimationComponent values that define the timing and feel of state transitions. Pass them to withAnimation or the .animation() modifier.
Spring
A spring animation with response and damping parameters. This is the most common animation type.
Spring(options?: {
response?: number;
dampingFraction?: number;
blendDuration?: number;
}): AnimationComponent;
Duration of the spring’s settle time in seconds. Lower values produce faster animations.
Damping ratio. 0 = no damping (infinite oscillation), 1 = critical damping (no bounce).
Duration in seconds for blending between animations.
const body = () => {
const [scale, setScale] = useState(1.0)
return VStack([
Circle()
.fill(Color("blue"))
.frame({ width: 100, height: 100 })
.scaleEffect(scale),
Button("Bounce", () => {
withAnimation(Spring({ dampingFraction: 0.5 }), () => {
setScale(scale === 1.0 ? 1.5 : 1.0)
})
})
])
}
InterpolatingSpring
A spring animation defined by physical stiffness, damping, and mass for precise control.
InterpolatingSpring(options: {
stiffness: number;
damping: number;
mass: number;
}): AnimationComponent;
Spring stiffness coefficient. Higher values produce faster, stiffer springs.
Damping coefficient. Higher values produce less bounce.
Mass of the spring. Higher values produce slower animations with more momentum.
const body = () => {
const [offset, setOffset] = useState(0)
return VStack([
Circle()
.fill(Color("red"))
.frame({ width: 50, height: 50 })
.offset({ x: offset, y: 0 }),
Button("Animate", () => {
withAnimation(InterpolatingSpring({
stiffness: 50,
damping: 10,
mass: 2
}), () => {
setOffset(offset === 0 ? 200 : 0)
})
})
])
}
EaseIn
An ease-in timing curve that starts slow and accelerates toward the end.
EaseIn(options?: { duration?: number }): AnimationComponent;
Animation duration in seconds.
const body = () => {
const [show, setShow] = useState(false)
return VStack([
Text("Hello")
.opacity(show ? 1 : 0),
Button("Fade In", () => {
withAnimation(EaseIn({ duration: 1.0 }), () => {
setShow(true)
})
})
])
}
EaseInOut
An ease-in-out timing curve that starts and ends slow with acceleration in the middle.
EaseInOut(options?: { duration?: number }): AnimationComponent;
Animation duration in seconds.
const body = () => {
const [rotation, setRotation] = useState(0)
return VStack([
Rectangle()
.fill(Color("purple"))
.frame({ width: 100, height: 100 })
.rotationEffect(rotation),
Button("Rotate", () => {
withAnimation(EaseInOut({ duration: 0.8 }), () => {
setRotation(rotation + 180)
})
})
])
}
EaseOut
An ease-out timing curve that starts fast and decelerates toward the end.
EaseOut(options?: { duration?: number }): AnimationComponent;
Animation duration in seconds.
const body = () => {
const [offset, setOffset] = useState(0)
return VStack([
Rectangle()
.fill(Color("green"))
.frame({ width: 100, height: 100 })
.offset({ x: offset, y: 0 }),
Button("Slide Out", () => {
withAnimation(EaseOut({ duration: 0.5 }), () => {
setOffset(300)
})
})
])
}
Linear
A linear timing curve with constant speed throughout.
Linear(options?: { duration?: number }): AnimationComponent;
Animation duration in seconds.
const body = () => {
const [position, setPosition] = useState(0)
return VStack([
Circle()
.fill(Color("orange"))
.frame({ width: 40, height: 40 })
.offset({ x: position, y: 0 }),
Button("Move", () => {
withAnimation(Linear({ duration: 2.0 }), () => {
setPosition(position === 0 ? 300 : 0)
})
})
])
}
Bouncy
A spring animation with extra bounce for playful, attention-grabbing effects.
Bouncy(options?: {
duration?: number;
extraBounce?: number;
}): AnimationComponent;
Approximate animation duration in seconds.
Extra bounce amount. 0 = no extra bounce, 1 = very bouncy.
const body = () => {
const [scale, setScale] = useState(1.0)
return VStack([
Text("Tap me!").font("title").scaleEffect(scale),
Button("Bounce", () => {
withAnimation(Bouncy({ extraBounce: 0.4 }), () => {
setScale(scale === 1.0 ? 1.3 : 1.0)
})
})
])
}
Snappy
A spring animation with higher damping for a quick, responsive feel.
Snappy(options?: {
response?: number;
dampingFraction?: number;
blendDuration?: number;
}): AnimationComponent;
Duration of the spring’s settle time in seconds.
Damping ratio. 0 = no damping, 1 = critical damping.
Duration in seconds for blending between animations.
const body = () => {
const [isExpanded, setIsExpanded] = useState(false)
return VStack([
Rectangle()
.fill(Color("cyan"))
.frame({ width: 200, height: isExpanded ? 200 : 100 }),
Button(isExpanded ? "Collapse" : "Expand", () => {
withAnimation(Snappy(), () => {
setIsExpanded(!isExpanded)
})
})
])
}
Chainable Modifiers
All animation constructors return an AnimationComponent that supports these chainable methods:
delay
Delays the start of the animation.
.delay(seconds: number): AnimationComponent
const animation = Spring().delay(0.5)
speed
Multiplies the animation speed.
.speed(multiplier: number): AnimationComponent
const slow = EaseInOut({ duration: 1.0 }).speed(0.5)
const fast = Linear({ duration: 2.0 }).speed(2.0)
repeatCount
Repeats the animation a fixed number of times.
.repeatCount(count: number): AnimationComponent
const bouncing = Bouncy().repeatCount(3)
repeatForever
Repeats the animation indefinitely.
.repeatForever(autoreverses: boolean | { autoreverses: boolean }): AnimationComponent
autoreverses
boolean | { autoreverses: boolean }
If true, the animation reverses direction each cycle. If false, it restarts from the beginning.
// Continuous rotation
const spinning = Linear({ duration: 2.0 }).repeatForever(false)
// Pulsing effect (forward and back)
const pulsing = EaseInOut({ duration: 1.0 }).repeatForever(true)
Combining modifiers
const body = () => {
const [offset, setOffset] = useState(0)
return VStack([
Circle()
.fill(Color("pink"))
.frame({ width: 60, height: 60 })
.offset({ x: offset, y: 0 }),
Button("Complex Animation", () => {
const animation = Bouncy({ extraBounce: 0.3 })
.delay(0.3)
.speed(0.5)
.repeatCount(3)
withAnimation(animation, () => {
setOffset(100)
})
})
])
}
Notes
- Default parameter values are platform-specific and optimized for each environment.
- Spring animations (
Spring, InterpolatingSpring, Bouncy, Snappy) may overshoot their target based on damping settings.
- Timing curve animations (
EaseIn, EaseInOut, EaseOut, Linear) run for a fixed duration and do not overshoot.
- Use
repeatForever sparingly to avoid performance issues.
See Also