Animation & Motion
Motion in Bunti is time-based: helpers are pure functions of elapsed time, so they render identically at any frame rate and need zero invalidation bookkeeping — the render loop already redraws every tick.
Progress over time
import { easeOutCubic } from '@zakmandhro/bunti';
// 0 → 1 over 400ms, eased
const t = ctx.animate(400, { id: 'intro', easing: easeOutCubic });
// looping: true wraps 0→1→0→1…, 'yoyo' bounces 0→1→0
const pulse = ctx.animate(1200, { id: 'pulse', loop: 'yoyo' });
ctx.restartAnimation('intro'); // replay on demandEnter & exit transitions
ctx.transition is the key primitive for immediate-mode UIs — it keeps an element mounted while it animates out:
const [open, setOpen] = ctx.useState('panel-open', false);
const t = ctx.transition('panel', open, { duration: 180 });
if (t.mounted) {
ctx.layer({ zIndex: 10 }, (overlay) => {
// slides in from one row up; slides back out on close
overlay.box({ x: 10, y: 6 + Math.round(1 - t.progress), width: 30, height: 8 }, drawPanel);
});
}progress runs 0→1 on enter and back 1→0 on exit (retargeting mid-flight if toggled quickly); mounted stays true until the exit finishes.
Staggered cascades
rows.forEach((row, i) => {
const p = ctx.stagger(i, { delay: 60, duration: 240 });
if (p > 0) drawRow(row, p); // rows cascade in, top to bottom
});Easing & interpolation
Fourteen curves ship: linear, easeIn/Out/InOut × Quad/Cubic/Quart, easeOutExpo, easeOutElastic, easeOutBounce, easeOutBack — plus lerp(a, b, t) and lerpRect(a, b, t) (cell-rounded) for positions and sizes, and ctx.fade(from, to, t) for colors.
Frame timing
For game loops and physics, the context exposes real timing:
ctx.dt; // ms since the previous frame (clamped to 100)
ctx.frame; // tick counter
ctx.elapsedTime; // ms since render() startedText effects
ctx.typewriter(text, { cps, blink })— grapheme-safe reveal with a block cursorctx.flicker(intensity, { interval })— deterministic, time-bucketed flicker (fps-independent)
Guidance
Terminal cells are chunky — 1-cell position steps read best over short distances. Keep UI transitions in the 150–250ms range, prefer color/brightness interpolation for smoothness, and lean on stagger for expensive-looking entrances that cost nothing.