
The slide-to-confirm button
Buttons, Physics, Transitions
NewFree
An import of 2,400 contacts made as a piece of wax honeycomb: every cell is a batch of contacts. A thread of honey runs down into the cell and the honey rises with its meniscus climbing the walls, pale where it is thin and dark where it is thick; when the batch is in a wax cap closes the cell from the walls to the middle and swells with a little bounce. The cells fill four at a time in a spiral from the middle. If a batch cannot be read its cell stays empty and the wax cracks; at the end a warm light runs across the sealed comb: Import 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 filling honeycomb</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/mona-sans@5.3.0/standard.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<main class="stage">
<!-- the filling honeycomb: a contacts import shown as a piece of wax comb. Every cell is a batch of contacts: it fills
with honey that rises with its meniscus, glowing where the light comes through, and when it is full a wax cap
closes over it from the walls inwards and swells a little. The cells fill in a spiral from the middle. The comb
is painted by script.js on the canvas, one cell at a time -->
<section class="favo" aria-label="Contacts import" data-favo>
<div class="favo__comb" role="progressbar" aria-label="Import progress" aria-valuemin="0" aria-valuemax="100"
aria-valuenow="0" aria-valuetext="Ready to import" data-comb>
<canvas class="favo__paint" aria-hidden="true" data-paint></canvas>
</div>
<div class="favo__info" aria-hidden="true">
<p class="favo__title">
<svg class="favo__tick" viewBox="0 0 24 24" data-tick><path d="M5.5 12.6l4.2 4.2 8.8-9.4" pathLength="1"/></svg>
<span class="favo__swap" data-title>contacts.csv</span>
</p>
<p class="favo__pct" data-pct>0%</p>
<p class="favo__meta"><span class="favo__swap" data-meta>2,400 contacts · 418 KB</span></p>
</div>
<div class="favo__buttons">
<button class="pill" type="button" data-go data-autoclic><span class="pill__label" data-label>Import contacts</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.
39 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 filling honeycomb” from Animorio and fit it into my siteThe cells are pointy topped hexagons on axial coordinates: x = R·√3·(q + r/2), y = 1.5·R·r. The ones whose centre lies inside an ellipse one radius smaller than the comb are batches; those between the two ellipses are half built cells, darkened towards black. Every corner of the grid is nudged by an amount taken from a hash of its rounded position, so all the cells that share it move it the same way and the comb stays closed but not perfect. The wall is the inner hexagon, shrunk towards the centre by WALL/2 ÷ cos 30°.
Wax, bottoms, the shade of the top walls and the light on the bottom ones go on a canvas of their own, at the start and at every resize. On every frame only the cells that changed are painted again: each one is clipped to its own hexagon, the same piece of the empty comb is copied over it with drawImage, and honey, thread, cap and cracks are drawn. Cells never overlap, so no cell dirties its neighbours. Only the final light paints everything, for just over a second; when nothing moves nothing is drawn.
The surface is a function of x: the level, less the meniscus rising near the walls with two exponentials (the walls are found by crossing the horizontal with the inner polygon), less a gaussian mound where the thread lands. The polygon is filled with a vertical gradient that starts at the surface and always has the same scale, so a cell just begun is pale and a full one reaches dark amber: more honey, less light. Over it go a dark radial gradient towards the walls, a light one in screen mode low in the middle and two lines of light under the surface.
The cells are sorted by hexagonal ring plus the angle round the centre (a spiral) or, with ORDER = 'wave', by a slanted line plus a little noise. WORKERS batches travel together, each with its own duration and sometimes a stall. The level follows the data with an exponential delay of THICK seconds, but with a minimum speed, otherwise the last per cent would never arrive. Once the cell is full, a GSAP timeline closes the cap like an iris (a hexagon with a hexagonal hole, filled evenodd), then swells it by 5% and lets it settle with elastic.out.
The batch that goes wrong runs its thread for 0.7 seconds without honey, then stops: four zigzag cracks worked out from a hash grow from the middle of the cell while it shudders, and the batches in flight finish by themselves. Retry closes the cracks and puts the batch back at the head of the queue. The comb is a role=progressbar with aria-valuenow and aria-valuetext updated at most every half second, aria-busy while it works and an aria-live line for the start, the failure, the end and a cancel. Clicks from a script (the library preview’s) never cancel and start again only after 2.4 seconds of Import complete.
| Name | File | Default | What it changes |
|---|---|---|---|
SECONDS | script.js | 7 | How long the demo import takes, in seconds (a real one follows its batches). |
CONTACTS | script.js | 2400 | The contacts to import: they are shared out among the cells. |
CELL | script.js | 19 | A cell’s radius, in units of the 380 wide drawing: smaller cells, more batches. From 14 to 26. |
WORKERS | script.js | 4 | How many batches are imported together, that is how many cells fill at a time. |
ORDER | script.js | 'spiral' | The order of the cells: 'spiral' in a spiral from the middle, 'wave' as a front from the left. |
FAIL_EVERY | script.js | 2 | In the demo, one import in how many goes wrong (0 never). |
FAIL_AT | script.js | 0.45 | Where in the import the batch that cannot be read is, from 0 to 1. |
THICK | script.js | 0.22 | How thick the honey is: the seconds the level takes to catch up with the data. |
CAP | script.js | 0.34 | How long the wax cap takes to close a full cell, in seconds. |
WORDS | script.js | { busy: 'Importing contacts', error: 'Import paused', done: 'Import complete' } | The words under the comb while importing, on failure and at the end; the one at rest is in index.html. |
LABELS | script.js | { busy: 'Cancel', error: 'Retry', done: 'Import again' } | The button’s words at the same three moments; the one at rest is in index.html. |
For importing contacts into a CRM or a newsletter, loading a CSV into a sheet or a database, syncing an address book, indexing documents or any job split into parallel batches where it is worth seeing which batches are done and which one stopped. The comb also suits a product with a warm, crafted tone.
The comb is 380 pixels wide and on a phone takes the width of the screen less 16 pixels a side (358 at 390): the drawing scales with the width and the cells stay the same. The pill is 44 tall and works by touch; the bead that gathers when the pill is pointed at and the swelling pill are only there with a mouse or a keyboard.
No thread, no rising honey, no iris and no bounce: the honey in each cell fades in as its batch arrives, then the cap fades in over it. The cracks fade in whole, without shuddering, and at the end there is no light crossing the comb: the tick appears. The words change with a fade.
GSAP 3.15.0, Mona Sans (font variabile) 5.3.0.
Compressed with gzip, the three demo files weigh 14 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.