
The slide-to-confirm button
Buttons, Physics, Transitions
NewFree
A laptop’s backup shown as a watch movement seen through a sapphire case back: brass wheels that really mesh, a lever that snaps and a balance swinging on its hairspring. Every tick of the escapement is two percent of the backup, and a long blued hand on the last wheel reads it off the scale on the case. If the disk comes loose the lever jams and the balance stops dead; at the end the balance runs down, a light passes over the metal and the backup is complete.
A folder that runs on its own: index.html, style.css, script.js and the libraries from a CDN. The React and Vue tabs hold the same demo as a ready component, which switches its animations off when it leaves the page.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
<title>The backup movement</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/saira@5.3.0/wdth.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<main class="stage">
<!-- the backup panel of a laptop, shown as a watch movement seen through its sapphire case back: brass wheels that
really mesh, a lever that snaps and a balance that swings on its breathing hairspring. Every tick of the
escapement is two percent of the backup, and a long blued hand on the last wheel reads it off the scale on the
case. The movement is painted on the canvas by script.js; the words and the button are HTML -->
<section class="backup" aria-labelledby="backup-title" data-backup>
<div class="backup__case" role="progressbar" aria-labelledby="backup-title" aria-valuemin="0" aria-valuemax="100"
aria-valuenow="0" aria-valuetext="Not backing up" data-bar>
<canvas class="backup__movement" aria-hidden="true" data-paint></canvas>
</div>
<div class="backup__foot">
<div class="backup__words">
<h2 class="backup__title" id="backup-title">
<span class="backup__swap" data-title>Studio laptop</span>
<svg class="backup__tick" viewBox="0 0 20 20" aria-hidden="true" data-tick><path d="M4.6 10.4l3.5 3.5 7.3-7.6" pathLength="1"/></svg>
</h2>
<p class="backup__meta"><span class="backup__swap" data-meta>Last backup yesterday at 18:40</span></p>
</div>
<div class="backup__side">
<p class="backup__figure" aria-hidden="true"><span class="backup__swap" data-figure>128 GB</span></p>
<button class="backup__btn" type="button" data-action data-autoclic><span class="backup__label" data-label>Back up now</span></button>
</div>
</div>
<p class="sr" role="status" aria-live="polite" data-live></p>
</section>
</main>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.15.0/dist/gsap.min.js"></script>
<script src="script.js"></script>
</body>
</html>Change values, colours and text with the controls and watch the animation respond live. Or write in the code yourself. Then download the folder with your changes.
30 values to change
With the Animorio connector, Claude Code takes it from here, guide included, and fits it into your project. Paste this request:
Take “The backup movement” from Animorio and fit it into my siteEvery wheel is drawn from its number of teeth z and its module m: pitch radius m·z/2, base radius with a 20° pressure angle, addendum one module and dedendum 1.25. The flank of every tooth is the involute, inv(α) = tan α − α, computed point by point between the base circle and the tip, with a little backlash. Wheels that mesh share a module and sit exactly the sum of their pitch radii apart; the phase of each one is worked out so that a gap faces the other’s tooth on the line of centres, and from there each turns by the ratio of the teeth, against its partner. So the teeth roll into each other and never overlap.
The escape wheel has fifteen teeth and a pinion of twelve, meshing with a last wheel of twenty four: the last wheel turns at half the speed. At every tick the escape wheel moves on by half a tooth, 12°, so the hand on the last wheel moves 6°: fifty ticks cover the 300° of the scale, and every tick is exactly two percent. The train goes on back to the barrel (a pinion of ten and a wheel of forty five, a pinion of ten and a barrel of fifty six), which turns only a few degrees over the whole backup.
The balance is isochronous: θ = A sin(ωt), at the same frequency whatever its amplitude. The lever only moves while the balance’s pin is in the fork, that is while |θ| is under the lift angle: there the lever’s angle follows the balance’s, outside it rests against its banking. Since the balance crosses that zone in a few milliseconds, the physics runs in steps of 1/1500 of a second and the lever really snaps within a frame. During the crossing the escape wheel takes its tick in three moves: a touch of recoil as it unlocks, the impulse along the pallet face, then the drop onto the other pallet.
A tick only starts if the bytes that have arrived cover it: otherwise the wheel stays locked, the balance gets no impulse and its amplitude dies away with a time constant of 2.4 s, like a watch running down. Every powered tick pushes the amplitude back towards the running one. Paused, a brake brings the constant down to 0.22 s, at the end to 0.28 s: the balance swings its last swings, still at the same frequency, and stops. On an error the balance switches to a stiff, lightly damped spring round the point where its pin meets the jammed fork, and shudders; the lever and the escape wheel take a blow on springs of their own.
The wheels’ brass is filled with a conic gradient that starts from the light’s direction less the wheel’s angle: the two bright sectors stay still while the wheel turns under them, like light on circular graining, and the rim catches a line of light at the top left. The perlaged plate (overlapping spots, each with its own conic gradient), the bridges with their Geneva stripes (parallel bands, each with the light running across it, and a broad sheen over them), the screws, the rubies, the case and the glass are painted once into three offscreen canvases; the lever, the balance, the hand and the ratchet are turned sprites. The balance is drawn at six moments of the frame with its opacity shared out, for motion blur, and the Archimedean hairspring turns every coil by its share of the angle.
| Name | File | Default | What it changes |
|---|---|---|---|
SECONDS | script.js | 6 | How long the demo’s bytes take to arrive, in seconds (a real backup follows its bytes; the movement never goes faster than fifty ticks). |
SIZE | script.js | 128 | The gigabytes to back up, also printed on the case. |
MACHINE | script.js | 'Studio laptop' | The computer being backed up. |
DISK | script.js | 'Archive' | The backup disk, the one that comes loose in the demo. |
BEAT | script.js | 5 | The balance’s frequency, in hertz: two ticks a swing, and every tick is 2% of the backup (5 is a high-beat watch, 36,000 beats an hour). |
SWING | script.js | 220 | How far the balance swings either way while it runs, in degrees. |
FAIL_EVERY | script.js | 2 | In the demo, one backup in how many goes wrong (0 never). |
FAIL_AT | script.js | 0.56 | How far the bytes of the backup that goes wrong get, from 0 to 1. |
GLINT | script.js | 0.9 | The light that passes over the metal when the backup is complete: 0 none, 1 bright. |
BLUR | script.js | 6 | How many moments of every frame the balance is painted at, for its motion blur (1 none). |
For a wait of a few seconds that has an outcome and suits a metaphor of precision: a backup, a safety copy, a long export, syncing an archive, checking a disk. The movement says “every piece lands in its place, one tick at a time” very well; for a one second load it is too rich, a simple bar is better.
The panel takes the screen’s width less 32 pixels (358 at 390) and the case stays 248 across, painted at the screen’s true density up to twice. The button is a 34 pixel pill: under a finger it squashes and springs back, and its words widen on the width axis only under the mouse. The long lines were shortened so that the line under the title sits beside the button even at 390.
The balance stays still and the lever does not snap: the wheels and the hand step along the scale with the bytes, because they are what says how far it has got. No jolt of the case on an error, no glint at the end, the hand goes back to zero at once; new words and the tick fade in.
GSAP 3.15.0, Saira (font variabile) 5.3.0.
Compressed with gzip, the three demo files weigh 20 KB; the libraries: GSAP 28 KB.
Tested on 8 October 2026
Use it in your own projects and in your clients’ projects. Do not resell it or redistribute it as is. GSAP stays under its own Standard license. Full license.
With your account’s email and password.
or with your email
You’re signed in as .
With your account, you can download the zip of every animation and every pack, for free.