Keyboard shortcuts

Press or to navigate between chapters

Press ? to show this help

Press Esc to hide this help

Motion & Interaction Nodes

Animation is a first-class IR concern in Voce IR. Every motion declaration includes a reduced-motion fallback, which the validator enforces as required. The compiler uses a tiered output strategy: CSS transitions, Web Animations API, then minimal requestAnimationFrame JavaScript.

AnimationTransition

Animates property changes between state machine states. The compiler chooses the optimal output technique based on the trigger type and interruptibility requirements.

FieldTypeRequiredDescription
node_idstringyesUnique identifier
namestringnoHuman-readable name
target_node_idstringyesNode to animate
trigger_state_machinestringnoStateMachine that triggers this animation
trigger_eventstringnoEvent on the state machine that starts animation
properties[AnimatedProperty]yesProperties to animate
durationDurationnoAnimation duration in ms
delayDurationnoDelay before animation starts
easingEasingnoTiming function (supports Spring)
reduced_motionReducedMotionnoRequired alternative for prefers-reduced-motion

AnimatedProperty

FieldTypeRequiredDescription
propertystringyesCSS-like property path (e.g., “opacity”, “transform.translateY”)
fromstringyesValue in the starting state
tostringyesValue in the ending state

Easing

The Easing table supports multiple timing function types.

FieldTypeRequiredDescription
easing_typeEasingTypenoLinear (default), CubicBezier, Spring, Steps, CustomLinear
x1, y1, x2, y2float32noControl points for CubicBezier
stiffnessfloat32noSpring stiffness (default 200)
dampingfloat32noSpring damping (default 20)
massfloat32noSpring mass (default 1)
stepsint32noStep count for Steps easing
points[float32]noPre-computed points for CustomLinear (CSS linear())
{
  "node_id": "fade-in",
  "target_node_id": "hero-section",
  "trigger_state_machine": "page-state",
  "trigger_event": "enter",
  "properties": [
    { "property": "opacity", "from": "0", "to": "1" },
    { "property": "transform.translateY", "from": "20px", "to": "0px" }
  ],
  "duration": { "ms": 300 },
  "easing": { "easing_type": "Spring", "stiffness": 300, "damping": 25, "mass": 1 },
  "reduced_motion": { "strategy": "Remove" }
}

Sequence

Choreographed animation timeline. Multiple AnimationTransitions played in sequence or parallel with stagger offsets.

FieldTypeRequiredDescription
node_idstringyesUnique identifier
namestringnoHuman-readable name
steps[SequenceStep]yesOrdered list of animation steps
staggerDurationnoDelay between sequential elements
iterationsint32noRepeat count, 0 = infinite (default 1)
alternateboolnoReverse on alternate iterations (default false)
reduced_motionReducedMotionnoAlternative for the entire sequence

SequenceStep

FieldTypeRequiredDescription
transition_idstringyesReference to an AnimationTransition node
delayDurationnoDelay before this step starts
parallelboolnoIf true, runs concurrently with previous step (default false)
{
  "node_id": "entrance-seq",
  "steps": [
    { "transition_id": "fade-in-title" },
    { "transition_id": "fade-in-subtitle", "delay": { "ms": 100 } },
    { "transition_id": "fade-in-cta", "delay": { "ms": 100 } }
  ],
  "stagger": { "ms": 50 },
  "reduced_motion": { "strategy": "Remove" }
}

GestureHandler

Maps touch, mouse, and keyboard input to state transitions or continuous property updates. The validator requires a keyboard_key for accessibility.

FieldTypeRequiredDescription
node_idstringyesUnique identifier
target_node_idstringyesNode that receives the gesture
gesture_typeGestureTypenoTap, DoubleTap, LongPress, Drag, Swipe, Pinch, Hover, Focus
trigger_eventstringnoState machine event to fire on gesture
trigger_state_machinestringnoTarget state machine
continuous_propertystringnoProperty to update for drag/continuous gestures
continuous_axisstringnoAxis for continuous gestures
keyboard_keystringnoKeyboard equivalent (required by validator)
keyboard_modifierstringnoModifier key (Shift, Ctrl, Alt, Meta)
threshold_pxfloat32noGesture distance threshold in pixels
velocity_thresholdfloat32noGesture velocity threshold
{
  "node_id": "card-tap",
  "target_node_id": "card-surface",
  "gesture_type": "Tap",
  "trigger_event": "select",
  "trigger_state_machine": "card-state",
  "keyboard_key": "Enter"
}

ScrollBinding

Binds node properties to scroll position. Compiled to CSS scroll-driven animations where supported, with IntersectionObserver fallback.

FieldTypeRequiredDescription
node_idstringyesUnique identifier
target_node_idstringyesNode whose properties are scroll-linked
scroll_triggerScrollTriggernoViewProgress (default) or ScrollProgress
scroll_axisScrollAxisnoVertical (default) or Horizontal
range_startfloat32noStart of scroll range, 0.0-1.0 (default 0.0)
range_endfloat32noEnd of scroll range, 0.0-1.0 (default 1.0)
properties[AnimatedProperty]yesProperties to animate over the scroll range
scroll_container_idstringnoScroll container (default: nearest ancestor)
reduced_motionReducedMotionnoAlternative for prefers-reduced-motion
{
  "node_id": "parallax-bg",
  "target_node_id": "bg-image",
  "scroll_trigger": "ViewProgress",
  "properties": [
    { "property": "transform.translateY", "from": "0px", "to": "-50px" }
  ],
  "reduced_motion": { "strategy": "Remove" }
}

PhysicsBody

Attaches physics simulation to a node for spring animations, momentum scrolling, and procedural motion. Non-interruptible springs are compiled to CSS linear() at build time.

FieldTypeRequiredDescription
node_idstringyesUnique identifier
target_node_idstringyesNode to apply physics to
stiffnessfloat32noSpring stiffness (default 300)
dampingfloat32noSpring damping (default 25, must be > 0)
massfloat32noSpring mass (default 1)
frictionfloat32noMomentum friction, 0-1 (default 0.05)
restitutionfloat32noBounciness, 0-1 (default 0)
interruptibleboolnoIf true, uses rAF instead of CSS (default false)
{
  "node_id": "spring-body",
  "target_node_id": "draggable-card",
  "stiffness": 400,
  "damping": 30,
  "mass": 1,
  "interruptible": true
}

ReducedMotion

Every animation must reference a ReducedMotion alternative. The validator rejects IR where any AnimationTransition, Sequence, or ScrollBinding lacks one.

FieldTypeRequiredDescription
strategyReducedMotionStrategynoRemove (default), Simplify, ReduceDuration, Functional
simplified_properties[AnimatedProperty]noReplacement properties for Simplify strategy
reduced_durationDurationnoShortened duration for ReduceDuration strategy

Strategy values:

  • Remove – snap to final state, no animation
  • Simplify – replace with a simpler animation (e.g., fade instead of slide)
  • ReduceDuration – keep the animation but make it near-instant
  • Functional – animation serves a functional purpose (spinner, progress); simplify but do not remove