Animation
QORM animations are declarative and cross-cutting: any node — a built-in widget or a component instance — can carry an animation prop and play an entrance effect. Entrance effects fire when a node mounts. The live update morphs the DOM in place, so an effect replays when a node is newly created (e.g. an item appended to a bound list), not on every state change.
The animation property (any node)
{ "type": "card", "animation": "fadeup", "duration": 450, "children": [ … ] }
Works the same on a component instance:
{ "type": "ProductCard", "animation": "pop", "props": { "name": "Cup" } }
Tuning props (all optional):
| prop | default | meaning |
|---|---|---|
animation | — | the effect name (below); bindable — "{{state.effect}}" lets an agent swap the animation by changing state |
duration | 450 | milliseconds |
delay | 0 | milliseconds before it starts (stagger a list by binding the index) |
curve | cubic-bezier(.34,1.2,.64,1) | easing |
repeat | 1 | play count (infinite for attention loops) |
Effects
- Enter:
fade,fadeup,fadedown,slideup,slidedown,slideleft,
slideright, scale, zoomout, rotate, flip, pop.
- Attention:
bounce,shake,pulse,spin(pair withrepeat).
Animated widgets
For value-driven (not entrance) motion, use the Flutter-style widgets:
animatedcontainer/animatedpadding/animatedalign/animatedpositioned
— smoothly transition style whenever a bound value changes (duration, curve).
animatedopacity— fade children to a boundopacity(0..1).transform/rotatedbox— static rotate / scale / translate.motion(andfadetransition,slidetransition,scaletransition,
rotationtransition, sizetransition, hero, animatedswitcher) — the same entrance effects as a dedicated wrapper widget.
The plain transition style prop (e.g. "transition": "all .2s") also applies to any node for simple CSS transitions.
Theme motion tokens
Skins carry the motion vocabulary alongside their colors. Each themes/*.json may declare a motion section; the native canvas backend consumes it directly, and the HTML/WebView backend exposes the same values as CSS custom properties:
"motion": {
"durationFast": 120,
"durationNormal": 250,
"durationSlow": 400,
"easingStandard": "easeOutCubic",
"easingEmphasized": "easeInOutCubic"
}
animatedcontainer/animatedopacitydefault todurationNormal+
easingStandard when the node sets no duration / curve prop — explicit props still win. On the HTML path this lands as var(--qorm-motion-normal) / var(--qorm-motion-standard), which hand-written transition styles can reference too.
- Easing names:
linear,easeIn,easeOut,easeInOut(plus the explicit
easeInCubic / easeOutCubic / easeInOutCubic spellings and the token aliases standard / emphasized).
- The built-in skins deliberately differ: the Apple palettes move at ~250 ms,
the WinUI palettes at ~167 ms — switching skins changes the app's tempo.
- Note: the HTML backend does not read
themes/*.json; it ships matching
defaults for the --qorm-motion-* variables. Per-skin JSON values apply on the native canvas backend.