
The send button
Buttons, Transitions, SVG
NewFree
The profile avatar of a hiking club's app, made like a cloisonné pin: gold wires bent into a drawing and enamels in the cells between them. Choosing another animal the enamels drain away, the gold wires lift, bend and slide into the new drawing and the new enamels run in from above cell by cell, still raw: pale, grainy, matte. Saving is the firing: the token glows from the rim inward and shimmers in the heat, the powder melts into glass, it cools from the rim and comes out glossy, with a polish that passes like a reflection.
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">
<title>The enamel avatar</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/lexend@5.3.0/index.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<main class="stage">
<!-- the avatar of a hiking club's app, made like a cloisonné pin in a round recess of the profile card.
Each choice drains the enamels, bends the gold wires into the new drawing and runs the new enamels into
its cells, still wet and matte; saving fires the token in the kiln, and it cools glossy. The token is
drawn on the canvas; the choices under it are real radio buttons -->
<section class="card" aria-label="Your avatar" data-card data-autoclic>
<div class="card__coin">
<span class="card__slot" aria-hidden="true"></span>
<canvas class="card__canvas" aria-hidden="true" data-canvas></canvas>
<button class="card__token" type="button" tabindex="-1" aria-label="Edit avatar" data-token></button>
</div>
<div class="card__body">
<div class="rest" data-rest>
<h2 class="rest__name">Maya Lindqvist</h2>
<p class="rest__meta">@maya.lind · Trail crew</p>
<button class="btn btn--line" type="button" data-edit>Edit avatar</button>
</div>
<form class="editor" data-editor>
<fieldset class="editor__row" data-who>
<legend class="sr">Picture</legend>
</fieldset>
<fieldset class="editor__row" data-tint>
<legend class="sr">Colour</legend>
</fieldset>
<div class="editor__actions">
<button class="btn btn--soft" type="button" data-cancel>Cancel</button>
<button class="btn btn--ink" type="submit" data-save>
<svg class="btn__tick" viewBox="0 0 24 24" aria-hidden="true" data-tick><path d="M5.5 12.6l4.1 4.1L18.6 7.4"/></svg>
<span class="btn__label" data-save-text>Save</span>
</button>
</div>
</form>
</div>
<p class="sr" 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.
40 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 enamel avatar” from Animorio and fit it into my siteEach illustration is written once, as SVG paths: the cells with their enamel (the walls) and the wires on their own. At start every wall becomes a loop of 64 evenly spaced points, taken with getPointAtLength from a hidden path of the page; an open wire becomes a loop that goes along it and comes back. Every cell knows where the enamel reaches it (its point nearest to a point above the token) and how far it has to run to fill.
A cell shows only where no later cell lies over it: it is clipped by its path and then, for each later walled cell that touches it, by «everything but that cell» (a big square with the path in it, even-odd). Successive clips intersect, so the subtraction is exact; the wires lying down are hidden the same way. The glints in the eyes have no wall and are laid on top.
Between two drawings the loops are paired by place and size, the closest pairs first; the new loop is turned (and reversed if needs be) so that its points line up with the old ones with the least travel. The points move with power3.inOut, but each starts a little after the one before (LAG), so the bend runs along the wire, in BEND seconds. Lifted, the wires cast a small shadow and are seen whole; lying down they cross-fade to the clipped version. A wire with no partner shrinks into its middle and fades, a new one grows out of its own.
The old enamels drain back towards the point they came in from; the new ones run in from above: each cell starts when the flow reaches it (its distance from the top over FLOW) and fills with a blot growing from its entry point, its edge wavering on two sines with a light rim like a wet edge. Enamel just laid is raw powder: paler, matte, with a fine grain of light and dark specks (GRAIN) and no gloss. A new colour runs into the field over the old one.
Save heats the token in FIRE[0] seconds: the heat comes in from the rim (a radial gradient of eleven stops, each with the heat at its radius, from dull red to the kiln's orange), the gold wires shine with a 'lighter' stroke, the light spreads on the card and the token shimmers, redrawn in 2-pixel strips pushed sideways by two sines; meanwhile the powder melts into glass. It stays hot until the save comes back (here a pretend one of SAVING seconds), then cools in FIRE[1] seconds from the rim to the middle, and a band of light runs along the diagonal lighting up the gold.
Animals and colours are real radio buttons with their aria-label in two fieldsets; Edit avatar takes the keys onto the chosen animal, the arrows change the choice, Escape cancels, on closing the focus goes back to Edit avatar, and an aria-live line says when the avatar is being saved, is saved or the changes are discarded. Going back to the saved avatar, what is still raw goes back to fired. Everything runs on GSAP's ticker only while something moves. A click from a script (the library's preview) tells a little story: it opens, chooses, saves, and again with other choices.
| Name | File | Default | What it changes |
|---|---|---|---|
INITIALS | script.js | 'ML' | The letters on the token when no animal is chosen (the first two). |
COLOURS | script.js | [['Midnight', '#24335c'], …] | The enamel colours of the field: name and colour. |
SAVED | script.js | [1, 1] | The avatar saved when the page opens: the animal (0 = the initials) and the colour. |
BEND | script.js | 0.5 | The seconds the gold wires take to bend into a new drawing. |
FLOW | script.js | 170 | How fast the wet enamel runs into the cells, in hundredths of the token a second. |
GRAIN | script.js | 0.4 | How grainy and matte the enamel looks before it is fired (0 = smooth). |
FIRE | script.js | [0.7, 1.1] | The kiln when saving: the seconds it takes to heat up and to cool down. |
SAVING | script.js | 0.9 | How long the pretend save takes, in seconds (in a real app, as long as the request). |
For the profile of an app or a community, choosing the avatar in a chat, a game or a club, the account settings of a service with illustrated avatars, a badge to collect, and in general for a draft that becomes final when it is saved.
The card is 352 pixels wide (less on a narrower screen) and 330 tall, and the six small tokens and six colours fit at 390 (on an even narrower screen they get a little smaller). Everything works by touch: a tap on the token opens the choices, or picks one at random with the choices open; the light that follows the mouse only moves to the spot touched on a phone.
No wires bending, no enamel running, no shimmer and no polish running across: the new face fades in over the old one, the token is there already made and the firing is an orange glow that fades in and out. Raw and fired still show, the light does not follow the pointer and the choices swap with the name with a fade.
GSAP 3.15.0, Lexend (font variabile) 5.3.0.
Compressed with gzip, the three demo files weigh 19 KB; the libraries: GSAP 28 KB.
Tested on 6 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.