Docs/Interface

Animation

Argui advances typed motions on one runtime frame clock on native platforms and WebAssembly. A settled motion does not keep requesting frames. A layout property such as width triggers layout, a background color triggers paint, and a transform or group opacity can use the retained compositor. The first composited frame may still need paint to establish its layer; choose the property for the effect you want, then inspect the presented result.

TSX: native loops and transitions

The built-in visual primitives expose native loops. The surface and its text move together here; the moving rectangle still reserves only its original 120 pixel width in layout.

Solid / React TSX
<rectangle width={280} height={56} padding={8} background="#e2e8f0">
  <rectangle width={120} height={40} padding={8} background="#2563eb"
    loopMs={900} loopTranslateX={120} loopPlaying={true}>
    <text color="#ffffff">Moving label</text>
  </rectangle>
</rectangle>

loopMs is the duration of one leg. Transform targets include loopTranslateX, loopTranslateY, and loopScale. Other targets include loopOpacity, loopBackground, loopWidth, loopRadius, and loopGap on their supported primitives. Loops alternate to the target and back; rotationLoopMs continuously rotates. loopPlaying={false} pauses the current phase. loopSteps makes discrete jump-end steps and is scheduled only at visible changes. The schema requires a 1–60,000 ms duration and positive step count. loopWidth requires an authored pixel width, loopRadius requires radii, loopGap requires gap, and loopBackground requires a solid base background. rotationLoopMs cannot be combined with another transform loop.

For a state change or a changed authored value, use a transition. Hover and press paint are native on rectangle, so JavaScript need not update the tree for their intermediate frames:

Solid / React TSX
<rectangle width={160} height={44} radii={8}
  background="#e2e8f0" hoverBackground="#bfdbfe"
  transitionMs={160} transitionTimingFunction="cubic-bezier(0.2, 0, 0, 1)">
  <text color="#0f172a">Hover me</text>
</rectangle>

transitionMs accepts 1–60,000 ms. transitionTimingFunction accepts linear or cubic-bezier(x1, y1, x2, y2) and requires transitionMs. transitionSpring selects the spring driver instead of a timed tween; do not combine it with transitionMs or transitionTimingFunction. See the active animation scenes for transform, steps, opacity, color, and width loops.

Rust: typed property motion

argui-animation::Motion<T> retains the presented value and target. Element::bind connects it to a typed argui-ui::property selector. Keep the motion alive across UI rebuilds if the same element should continue its animation.

Rust
use argui_animation::{Duration, Motion, Tween};
use argui_ui::{Element, property};

let opacity = Motion::new(1.0_f32);
let panel = Element::container([Element::text("Fading panel")])
    .opacity(1.0)
    .bind(property::LayerOpacity, opacity.clone());
opacity.animate_to(0.4, Tween::new(Duration::from_millis(240)));

LayerOpacity fades the group including descendants. property::Opacity changes the element's painted quad opacity; it is a different property. Neither one makes invisible content automatically noninteractive or removes its accessibility semantics. Disable interaction or hide semantics separately when that behavior is needed.

Motion::animate_to retargets from the current presented value. Motion::spring_to also preserves velocity and returns an error for invalid physics parameters. A direct binding has final precedence over an implicit style transition for the same property. Timeline<T> and Keyframes<T> offer delays, iteration, direction, fill, per-keyframe easing, and holds; ScheduleBuilder composes cues and staggered work. Curves include linear, cubic Bézier, steps, piecewise linear, and a thread-safe custom function. Spring, decay, and inertia drivers are separate from easing curves because they retain velocity.

What updates

Property family Typical update path
Transform and group opacity Composition, with hit geometry updated for transforms
Solid or compatible gradient paint, border, radius, shadow Paint or layer update
Width, height, minimum/maximum, padding, gap, grow/shrink, pixel insets Layout
Scroll offset Scroll translation

Gradient interpolation requires compatible kinds and stop structure; incompatible values switch discretely. A complete LayoutStyle replacement is also discrete. Reduced-motion preference finishes active property motions at their targets and prevents subsequent motion from running across frames while it is active. Hidden retained pages do not schedule their native loops. Explicit width, gap, and other layout property motions are supported; insertion, removal, and reordering do not automatically create captured before/after geometry transitions.

argui-animation owns timing and interpolation, argui-ui resolves bound values on stable nodes, and the runtime schedules frames. The renderer does not own timeline state. The animation tests cover compositor, stepped, reduced-motion, and hidden-page scheduling. Transitions for conditional Rust styles are described in styling.