
The slide-to-confirm button
Buttons, Physics, Transitions
NewFree
The note sync of an app as a seedling growing in a small clay pot: the shoot comes out of the seed bent in a hook, the stem climbs towards the light and branches, every leaf unrolls from a fold and the whole plant sways on springs. The plant is the progress bar; at the end a flower opens on the bud. If the connection drops the plant wilts a little until Retry straightens it, and every sync grows a different plant from a new seed.
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 sync sprout</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/bricolage-grotesque@5.3.0/standard.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<main class="stage">
<!-- the sync of a notes app, shown as a seedling in a small clay pot. Pressed, the seed in the soil shivers while
the app looks for changes, then it splits and a shoot comes up in a hook, opens its two seed leaves and
climbs: the stem branches, every leaf unrolls from a fold, the whole plant sways on springs. The plant is the
progress. When every note is in, the bud on top opens into a flower; if the connection drops the plant wilts
until Retry. Every sync grows a slightly different plant from a new seed. The plant and the pot are drawn by
script.js on the canvas; the words and the button are HTML -->
<section class="sprout" aria-labelledby="sprout-title" data-sprout>
<div class="sprout__scene" role="progressbar" aria-labelledby="sprout-title" aria-valuemin="0" aria-valuemax="100"
aria-valuenow="0" aria-valuetext="Not syncing" data-scene>
<canvas class="sprout__paint" aria-hidden="true" data-paint></canvas>
</div>
<div class="sprout__foot">
<div class="sprout__words">
<h2 class="sprout__title" id="sprout-title"><span class="sprout__swap" data-title>Notes</span></h2>
<p class="sprout__meta"><span class="sprout__swap" data-meta>Last synced 2 hours ago</span></p>
</div>
<button class="sprout__btn" type="button" data-action data-autoclic><span class="sprout__label" data-label>Sync now</span></button>
</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.
38 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 sync sprout” from Animorio and fit it into my siteThe seed is a number feeding a pseudo random generator (mulberry32): from it comes the skeleton of the plant, once per sync. The stem is a row of segments from joint to joint; the first three are the hypocotyl that comes up in a hook, then every joint has a leaf, alternately right and left, and with some probability a side shoot of two or three segments with its own leaves. The bend of every segment turns its angle a little towards the window (phototropism) and adds a small zigzag away from the leaf. Every piece knows when it starts to grow and how long it takes, in units of progress: everything is done before 95%, and the last stretch goes into the bud.
Every frame the skeleton is laid out for the progress shown, joint by joint from the soil up: every segment is as long as its growth, its angle is added to the one of the segment below, the branches start from their joint. The thickness is worked out from the tip: thin at the top, 0.048 pixels wider for every pixel of stem above, with a cap that grows with the plant. Before it starts the plant is laid out fully grown and scaled uniformly so that the flower and the leaves fit the box, whatever seed comes up. The progress follows the data on a critically damped spring that never goes back.
The joints of a branch go through a Catmull-Rom curve; along the curve a tapering ribbon (the edges either side of the normal, the tip rounded) makes the stem, with two narrower ribbons on top moved towards the light and the shade. A leaf is a midrib that curves (downwards with its weight, towards the stem while it is young) and two halves that close like the pages of a book: the width you see is the real one times the cosine of the fold. The half facing up catches the light, the other stays in shade, and on top come the side veins curving out towards the margin, a darker edge and a soft shadow.
Every segment and every leaf has an extra angle on a damped spring (26% of critical damping, worked out in steps of 1/240 of a second): the breeze is a target that sways on two sines, the wilting is a target that bends the segments towards the side of the light and the leaves downwards, and the pointer gives every piece near it the turn of its push (the cross product of the piece and the pointer’s velocity). When the wilting target goes back to zero quickly, the springs overshoot and the plant straightens with a bounce.
The seed coat stays on the tips of the seed leaves until they open, then it falls with its own gravity and bounces on the soil. The flower is drawn in simple three dimensions: an axis tilted towards the viewer, every petal a direction that opens out from the axis by an angle going from shut to open on an elastic staggered petal by petal; the petals are projected onto the plane, sorted from the furthest and lit by their normal. Sync again winds the progress back to zero and drops a new seed in with a bounce.
The drawing is a role=progressbar with aria-valuenow and an aria-valuetext in notes, the section has aria-busy while it works and an aria-live line says when the sync starts, stops, loses the connection and ends. The button changes its word (Sync now, Pause, Resume, Retry, Sync again) and the pill takes the new width with a little bounce; a click from a script, the library preview’s, never pauses. When nothing moves the canvas is not redrawn.
| Name | File | Default | What it changes |
|---|---|---|---|
NOTES | script.js | 846 | How many notes the app syncs. |
SECONDS | script.js | 5.5 | How long a sync takes in the demo, in seconds (a real one follows its notes). |
FAIL_EVERY | script.js | 2 | In the demo, one sync in how many loses the connection (0 never). |
FAIL_AT | script.js | 0.56 | How far the sync that loses the connection gets, from 0 to 1. |
SEED | script.js | 11 | The first plant’s seed; every sync after it grows from a new one. |
NODES | script.js | 8 | How many joints the main stem grows. |
BRANCHING | script.js | 0.5 | How likely a joint is to grow a side shoot, from 0 to 1. |
LIGHT | script.js | 0.6 | How hard the plant leans towards the light, from 0 to 1. |
PETALS | script.js | 5 | The petals of the flower. |
SWAY | script.js | 1 | How much the breeze moves it: 0 still, 1 a little, 2 a lot. |
DROOP | script.js | 1 | How far it wilts when the connection drops: 0 not at all, 1.5 a lot. |
FOLLOW | script.js | 0.4 | How long the plant takes to catch up with the notes, in seconds. |
For a wait of a few seconds that has an outcome, in an app with a gentle tone: syncing notes, a journal, a backup, importing a library. The plant says «it is growing, all is well» better than a bar, and the wilting reads without words; for a one second load or a technical app something drier is better.
The component takes the screen’s width less 32 pixels (358 on a 390 screen) and stays 290 tall; the plant is scaled to fit the box and the canvas paints at the screen’s real density, up to twice. With a finger, a tap pushes the nearby leaves away and a sideways drag stirs them; scrolling up and down stays with the page. The button squashes and springs back, and its words widen on the width axis only under the mouse.
No breeze, springs, shivers, starts or bounces: the plant still grows, because it is what says how far along things are, but every piece is already in place; the coat is on the soil at once, the wilting and the straightening are immediate, the flower opens at once, and Sync again moves to the new plant with a fade. The new words fade in and the tick is not drawn.
GSAP 3.15.0, Bricolage Grotesque (font variabile) 5.3.0.
Compressed with gzip, the three demo files weigh 17 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.