Loading sequence
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.
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
- Define a plain array of step objects, each with a status string and an optional scramble duration.
- Track state as
'idle' | 'loading' | 'success', plus a current step index and the current status text. - Render the spinner element only while
state === 'loading', and animate it withuseWaapiAnimate, spinning it to 360° on a linear, looping ease. - Bind the status line to
useScrambleTextwith a reactive computed target built from the current step's text. Changing that text is enough to trigger a new scramble. - Advance steps with a
setTimeoutchain: each step's scramble duration plus a fixed reading pause sets the wait before advancing again. - 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.
- On the last step, switch state to
'success'and animate a checkmark in withuseAnimate.
Using the nanime Nuxt module, build a Vue 3 terminal-style build-log
component with three states: idle, loading, success. Define an array of
build step objects, each with its status text and an optional
scrambleDuration that overrides a shared default.
On start, cycle through the steps with a setTimeout chain, showing
"[n/total] step text" as the current status. Bind the status text to
useScrambleText(statusEl, { duration }, { text: currentText, chars:
'0123456789abcdef', settleDuration: 300, revealRate: 20 }) using a reactive
computed target, so each step change triggers a new scramble automatically
without any imperative call.
While state is loading, render a spinner icon animated with
useWaapiAnimate(spinnerEl, { rotate: { to: 360 }, duration: 800,
ease: 'linear', loop: true }).
Add pause and resume: pausing calls clearTimeout on the step timer and
pauses the spinner instance. Resuming plays the spinner again and sets a new
timeout for the current step's full wait (its scramble duration plus the
reading pause), not the portion that was left when it paused.
When the last step completes, switch state to success, show a checkmark
element, and animate it in with useAnimate (opacity from 0 to 1, scale
from 0.8 to 1, outQuad ease, 300ms).