Examples

Loading sequence

Idle to loading to success.

A terminal-style build log. Hit run and a spinner starts turning while a status line scrambles from one build step to the next, until the sequence finishes and a checkmark pops in to confirm success. Pause mid-build and both the spinner and the step timer stop together. Resume and the spinner carries on from the angle it stopped at, while the current step waits out its full pause again before the log moves on.

$nanime build
> Ready to build
View on GitHub

What's happening

Hit Run and the log starts ticking through build steps one at a time, a spinner turning next to the status line. Each step's text doesn't swap in. It scrambles through random characters before settling on the new line, like an old terminal typing itself out. When the last step finishes, the spinner is replaced by a checkmark that pops in.

How it's built

Three composables split the work by state: useWaapiAnimate spins the icon (off the main thread, so it doesn't stutter under other work), useScrambleText handles the text transition between steps, and useAnimate pops the checkmark in at the end.

The build steps are a plain array of objects, each with its text and an optional scramble duration. Advancing through them is a setTimeout chain: a step's scramble duration plus a fixed reading pause sets how long to wait before moving to the next one. Pausing clears that timer, and resuming sets a fresh one for the current step, so the step it was on waits out its full pause again rather than the part that was left.

The scramble needs no imperative trigger. Its target text is a reactive computed value tied to the current step index, so useScrambleText(statusEl, { duration }, scrambleConfig) picks up the change the moment the step advances and animates the transition on its own.

The spinner and success mark are scoped to their own state too. The spinner element exists in the DOM only while loading, and the success mark only while succeeded, so each composable only ever applies to an element that's there.

Building it yourself

  1. Define a plain array of step objects, each with a status string and an optional scramble duration.
  2. Track state as 'idle' | 'loading' | 'success', plus a current step index and the current status text.
  3. Render the spinner element only while state === 'loading', and animate it with useWaapiAnimate, spinning it to 360° on a linear, looping ease.
  4. Bind the status line to useScrambleText with a reactive computed target built from the current step's text. Changing that text is enough to trigger a new scramble.
  5. Advance steps with a setTimeout chain: each step's scramble duration plus a fixed reading pause sets the wait before advancing again.
  6. Pause by clearing that timer and pausing the spinner instance. Resume by playing the spinner again and setting a fresh timer for the current step.
  7. On the last step, switch state to 'success' and animate a checkmark in with useAnimate.
Copyright © 2026