Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/Augani/kael/llms.txt

Use this file to discover all available pages before exploring further.

Kael’s animation system is built around explicit, data-driven descriptions of motion. You construct an Animation value, pick an Easing curve and a Repeat strategy, then attach it to any element via the AnimationExt trait. The framework samples each animation on every frame and calls your animator closure with a normalized delta in [0.0, 1.0], leaving the actual style changes entirely in your control.

Animation

Animation describes a single motion segment: its duration, easing, delay, and repeat behaviour.
rust
pub struct Animation {
    duration: Duration,   // required at construction
    easing:   Easing,     // default: Easing::Linear
    delay:    Duration,   // default: Duration::ZERO
    repeat:   Repeat,     // default: Repeat::Once
}

Animation::new

rust
pub fn new(duration: Duration) -> Animation
Creates an animation with the given duration. All other fields take their defaults (Linear easing, no delay, play once).
rust
use std::time::Duration;

let anim = Animation::new(Duration::from_millis(300));

Builder methods

Each method consumes self and returns a new Animation, so you can chain them.
.easing(easing)
fn(Easing) -> Animation
Sets the easing curve to one of the built-in Easing variants.
.with_easing(f)
fn(impl Fn(f32) -> f32 + 'static) -> Animation
Sets a custom easing function. The closure receives a normalized progress value in [0.0, 1.0] and must return a value in the same range. Internally this wraps the closure in Easing::Custom(Rc::new(f)).
.delay(delay)
fn(Duration) -> Animation
Adds a delay before the animation begins. During the delay, AnimationSample::started is false and delta is 0.0.
.repeat(repeat)
fn(Repeat) -> Animation
Sets the repeat strategy to any Repeat variant.
.repeat_forever()
fn() -> Animation
Shorthand for .repeat(Repeat::Forever).
rust
let anim = Animation::new(Duration::from_millis(400))
    .easing(Easing::EaseInOut)
    .delay(Duration::from_millis(100))
    .repeat(Repeat::Count(3));

Easing

The Easing enum selects the curve applied to the raw linear progress value before it is delivered to your animator.
rust
pub enum Easing {
    Linear,
    EaseIn,       // quadratic ease-in
    EaseOut,      // quadratic ease-out
    EaseInOut,    // quadratic ease-in-out
    CubicBezier(f32, f32, f32, f32),  // CSS-style control points (x1, y1, x2, y2)
    Spring {
        stiffness: f32,
        damping:   f32,
        mass:      f32,
    },
    Custom(Rc<dyn Fn(f32) -> f32>),
}
Linear
variant
Returns the input unchanged (delta). Equivalent to the CSS linear timing function.
EaseIn
variant
Applies a quadratic ease-in curve (delta * delta). Motion starts slow and accelerates.
EaseOut
variant
Applies a quadratic ease-out curve (1 - (1 - delta)²). Motion starts fast and decelerates.
EaseInOut
variant
Applies a quadratic ease-in-out curve. Motion accelerates through the first half and decelerates through the second.
CubicBezier(x1, y1, x2, y2)
variant
A cubic Bézier curve with CSS-style control points, solved numerically with 12 binary-search iterations. Pass (0.25, 0.1, 0.25, 1.0) to reproduce the CSS ease curve.
Spring { stiffness, damping, mass }
variant
A damped spring model. Higher stiffness produces a snappier motion; higher damping removes oscillation; mass controls inertia.
Custom(Rc<dyn Fn(f32) -> f32>)
variant
An arbitrary easing callback. Use .with_easing(|t| ...) on Animation to construct this variant without naming the type.

Easing helper functions

The kael::animation::easing module exposes free functions you can compose or pass directly to .with_easing:
rust
use kael::animation::easing;

// Quintic ease-out — returns a closure
let anim = Animation::new(Duration::from_millis(500))
    .with_easing(easing::ease_out_quint());

// Bounce — wraps any easing to play forward then backward
let anim = Animation::new(Duration::from_millis(600))
    .with_easing(easing::bounce(easing::ease_out));

// Pulsating alpha between two values
let anim = Animation::new(Duration::from_millis(1200))
    .with_easing(easing::pulsating_between(0.4, 1.0))
    .repeat_forever();

Repeat

Controls how many times an animation plays.
rust
pub enum Repeat {
    Once,          // play once, then stop at delta = 1.0
    Count(u32),    // play a fixed number of times
    Forever,       // loop indefinitely, delta never reaches 1.0
}
Once
variant
Default. The animation plays a single time. AnimationSample::finished becomes true when delta reaches 1.0.
Count(u32)
variant
The animation repeats for the given number of full cycles. After duration * count has elapsed, finished is true and delta is 1.0.
Forever
variant
The animation loops indefinitely. finished is always false. Useful for loading spinners, pulsing indicators, or ambient motion.

AnimationSample

AnimationSample is the internal output of Animation::sample. You rarely construct one yourself, but understanding its fields helps when writing custom animators.
rust
pub(crate) struct AnimationSample {
    pub delta:    f32,  // eased progress in [0.0, 1.0]
    pub started:  bool, // false while still in the delay period
    pub finished: bool, // true after the final cycle completes
}

AnimationExt trait

The AnimationExt trait extends any element or component with methods that wrap it in an AnimationElement. Import it from the elements module to bring the methods into scope.

with_animation

rust
fn with_animation(
    self,
    id: impl Into<ElementId>,
    animation: Animation,
    animator: impl Fn(Self, f32) -> Self + 'static,
) -> AnimationElement<Self>
Wraps the element with a single animation. The animator closure receives the element and the current eased delta (0.01.0) on each frame, and must return the styled element.
rust
div()
    .bg(theme.colors.surface)
    .with_animation(
        "fade-in",
        Animation::new(Duration::from_millis(250)).easing(Easing::EaseOut),
        |el, delta| el.opacity(delta),
    )

with_animations

rust
fn with_animations(
    self,
    id: impl Into<ElementId>,
    animations: Vec<Animation>,
    animator: impl Fn(Self, usize, f32) -> Self + 'static,
) -> AnimationElement<Self>
Wraps the element with a chain of animations. The animator receives the element, the index of the currently active animation, and its local delta.

with_animation_sequence

rust
fn with_animation_sequence(
    self,
    id: impl Into<ElementId>,
    sequence: AnimationSequence,
    animator: impl Fn(Self, usize, f32) -> Self + 'static,
) -> AnimationElement<Self>
Convenience wrapper over with_animations that accepts an AnimationSequence directly, consuming it into its scheduled Vec<Animation>.

with_keyframes

rust
fn with_keyframes(
    self,
    id: impl Into<ElementId>,
    keyframes: Keyframes,
    animation: Animation,
) -> AnimationElement<Self>
where
    Self: Sized + Styled + 'static
Drives a CSS-like keyframe animation on a Styled element. The Keyframes value handles interpolation; you only supply timing via Animation.
rust
let frames = keyframes()
    .at(0.0, |f| f.opacity(0.0).scale(0.95))
    .at(1.0, |f| f.opacity(1.0).scale(1.0));

my_panel.with_keyframes(
    "panel-appear",
    frames,
    Animation::new(Duration::from_millis(200)).easing(Easing::EaseOut),
)

animation (compact form)

rust
fn animation(
    self,
    id: impl Into<ElementId>,
    keyframes: Keyframes,
    animation: Animation,
) -> AnimationElement<Self>
where
    Self: Sized + Styled + 'static
Alias for with_keyframes. Prefer this in component render methods where brevity matters.

AnimationSequence

AnimationSequence schedules a series of Animation values back-to-back, automatically offsetting each one so it starts after the previous ends.
rust
pub struct AnimationSequence {
    animations: Vec<Animation>,
}
rust
let seq = AnimationSequence::new()
    .then(Animation::new(Duration::from_millis(200)).easing(Easing::EaseOut))
    .then(Animation::new(Duration::from_millis(300)).easing(Easing::EaseIn))
    .with_overlap(Duration::from_millis(50)); // last animation starts 50ms earlier
.then(animation)
fn(Animation) -> AnimationSequence
Appends an animation that starts after the current tail’s scheduled_end. Any delay on the new animation is added on top.
.then_for(duration)
fn(Duration) -> AnimationSequence
Shorthand for .then(Animation::new(duration)).
.with_overlap(overlap)
fn(Duration) -> AnimationSequence
Subtracts overlap from the delay of the most recently added animation, causing it to start before the previous one finishes.
.into_animations()
fn() -> Vec<Animation>
Consumes the sequence and returns the flat, scheduled Vec<Animation>.

Keyframes

Keyframes lets you declare CSS-style keyframe stops at normalized progress positions. Kael linearly interpolates between adjacent stops.
rust
pub struct Keyframes {
    frames: Vec<Keyframe>,
}
Build a Keyframes value with the free function keyframes():
rust
let frames = keyframes()
    .at(0.0, |f| f.opacity(0.0).scale(0.8))
    .at(0.5, |f| f.opacity(1.0).scale(1.05))
    .at(1.0, |f| f.opacity(1.0).scale(1.0));
Frames are automatically sorted by progress, so insertion order does not matter.

StyledKeyframe

A single keyframe stop that can hold optional values for opacity, scale_x, scale_y, and rotate_degrees. Only fields that are set participate in interpolation; unset fields on adjacent stops are passed through unchanged.
rust
pub struct StyledKeyframe {
    opacity:        Option<f32>,
    scale_x:        Option<f32>,
    scale_y:        Option<f32>,
    rotate_degrees: Option<f32>,
}
MethodDescription
.opacity(f32)Sets the target opacity.
.scale(f32)Sets uniform X and Y scale.
.scale_xy(f32, f32)Sets independent X and Y scale.
.rotate(f32)Sets the target rotation in degrees.

AnimationHandle

If you need to cancel an in-flight animation, use the with_cancellable_animation variant (on AnimationExt) which returns both the AnimationElement and an AnimationHandle.
rust
pub struct AnimationHandle {
    cancelled: Rc<Cell<bool>>,
}
.cancel()
fn()
Signals the animation to jump to its final state on the next frame.
.is_cancelled()
fn() -> bool
Returns true if .cancel() has been called.
AnimationHandle is Clone, so you can share it across closures — for example, to cancel a loading animation when a network request resolves.

Build docs developers (and LLMs) love