Skip to content
animorio
IT
All components

The moka pot loader

Loading, Physics, SVG, TransitionsCanvas, GSAPAdvancedCompressed weight: Demo 22 KBGSAP 28 KBFreeDownload the zip

An export made as a moka pot on the stove, cut away on the right like a technical drawing: inside you see the water in the boiler, the funnel of ground coffee and the chimney in the middle of the upper chamber. Press Export report and the blue flame catches from the igniter and runs round the ring, the water goes down and the coffee climbs the chimney, wells over and runs down into the chamber: its level is the percentage. At the end the pot sputters, throws up spurts of foam, hisses steam from the spout and from under the rattling lid, and the gas goes out: Report ready.

The code

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 moka pot loader</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 moka pot loader: an export shown as a stovetop moka pot on a small gas ring, its right side cut away like a
         technical drawing so you see the water in the boiler and the chimney in the upper chamber. Pointed at, the
         button makes the igniter spark; pressed, the blue gas lights, the water goes down, the coffee comes up the
         chimney and runs into the chamber, and its level is the export's progress. At the end the pot sputters and
         hisses, the gas goes out and the report is ready to download. The pot is drawn by script.js -->
    <section class="moka" aria-label="Report export" data-moka>
      <!-- four layers, bigger than the pot's place so the steam has room above it: the burner and the inside of the
           pot; the flame and the liquids; the outside and the hatched cut; the steam -->
      <div class="moka__scene" role="progressbar" aria-label="Report export" aria-valuemin="0" aria-valuemax="100"
           aria-valuenow="0" aria-valuetext="Ready to export" data-scene>
        <div class="moka__layers" data-layers>
          <svg class="moka__art" viewBox="25 40 250 290" preserveAspectRatio="none" aria-hidden="true" data-art="back"></svg>
          <canvas class="moka__art" aria-hidden="true" data-fluid></canvas>
          <svg class="moka__art" viewBox="25 40 250 290" preserveAspectRatio="none" aria-hidden="true" data-art="front"></svg>
          <canvas class="moka__art" aria-hidden="true" data-air></canvas>
        </div>
      </div>
      <p class="moka__status" aria-hidden="true">
        <svg class="moka__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="moka__swap" data-status>Ready to export</span>
        <span class="moka__pct" data-pct></span>
      </p>
      <div class="moka__buttons">
        <button class="pill" type="button" data-go data-autoclic><span class="pill__label" data-label>Export report</span></button>
        <button class="pill is-quiet" type="button" hidden data-again><span class="pill__label">Brew again</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>

Playground

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.

51 values to change

Or ask Claude Code for it

With the Animorio connector, Claude Code takes it from here, guide included, and fits it into your project. Paste this request:

Take “The moka pot loader” from Animorio and fit it into my site

What it does

On a white background, alone in the middle, an eight-sided aluminium moka pot on a small gas ring: the boiler at the bottom with its brass valve, the waist with its collar, the upper chamber flaring upwards with its pointed spout, the lid with its black knob and the hinged bakelite handle. On the left the brushed aluminium, its faces catching the light differently: the boiler looks up at the light, the upper chamber a little down. On the right the pot is cut away like a technical drawing, with the cut walls hatched and the centre line: inside are the blue water in the boiler, the funnel full of ground coffee with its stem dipping into the water, the perforated filter, the gasket, the thread between boiler and chamber and, in the middle of the empty chamber, the chimney. Below is the gas ring, with the cast iron pan support, the burner and the igniter, then the line Ready to export and the Export report button. Pointing at the button makes the igniter give three sparks. Pressed, the blue flame catches next to the igniter and runs round the ring, the water climbs the stem and the grounds darken as they soak, the coffee climbs the chimney, wells over its top in a dome and runs down its sides in two streams. In the chamber the level rises with the percentage (Brewing your report… 48%), dark with the pale crema on top, small bubbles and a little foam, while the water in the boiler goes down and bubbles rise from its hot bottom. The export moves in fits and starts: when it runs the stream gurgles and throws a few drops, in the pauses it shrinks to a trickle. At 100% the water drops below the funnel and steam blows through the stem in slugs; the chimney throws up three spurts of foam, steam hisses from the spout and from under the lid, which rattles on its hinge, and the flame goes out. The line becomes Report ready with a green tick that draws itself, Brew again appears next to Download, and a wisp of steam still rises from the spout. Brew again pours the coffee out, fills the boiler again and puts dry grounds back in.

How it works

An octagon seen from the front

Of an octagon seen from the front you see three faces: the front one ends at tan 22.5° of the half width (0.414), the two slanted ones go from there to the edge. The pot’s profile gives the half width at every height (the boiler narrows going up, the upper chamber flares), and every band (lid, rim, chamber, collar, boiler, bevel) is drawn once in SVG with a gradient for each face, chosen by how the face is tilted towards the light. On the slanted face a blurred white strip is the reflection, and over it lies a pattern of thin random lines, always the same, for the brushed finish; everything is clipped to the left of the cut line.

The cut, in four layers

Right of the cut the walls are polygons filled with two hatch patterns, at 45° and at −45°, because two parts that touch in a technical drawing have opposite hatching: the boiler with its base, the chamber with its floor and the chimney, the lid. The funnel’s sheet metal is a solid line, the filter and the funnel’s bottom a dashed one, the thread a zigzag. There are four layers: at the back the inside of the pot and the burner (SVG), then a canvas with the flame and the liquids, then the outside and the cut walls (SVG), and over everything a canvas with the steam. So the liquids’ edges end under the hatching, and every frame only the two canvases are painted again.

The level is the percentage

The demo’s export is a list of steps, each a jump forward or a pause: the weights change a little every time but together they last SECONDS. The coffee’s level goes from the chamber’s floor to full with the percentage, the water’s from a full boiler down to the funnel’s stem. How hard the coffee comes out of the chimney follows the speed of the progress, smoothed: 0.14 + 1.6 × speed, so the stream gurgles on the jumps and stays a trickle in the pauses. The gurgle is the sum of two sines, plus a jump now and then that swells the dome and throws two drops; the streams down the chimney widen and narrow with a wave that runs down them.

A surface that sloshes

The coffee’s surface, and the water’s, is a row of 40 points under a damped wave equation: v += (c²/dx² · (h₋₁ + h₊₁ − 2h) − d·v − 5h)·dt, in steps of 5 thousandths of a second, with walls that reflect. The streams push it down where they fall, the drops where they land, bursting bubbles pull it up; in the coffee the bubbles carried down by the streams rise again and float as foam. When the biggest ripple is below 0.04 units the surface rests, and when nothing moves the loop stops drawing.

The flame and the sputter

Eighteen flames sit on an ellipse round the burner’s cap: they are painted from the back to the front with the cap in between, each a drop with a pale cone inside, bent outwards and pressed flat under the pot, and they flicker with two sines. They light in order, starting from the igniter. At the end the water drops below the stem and steam blows through it in slugs; the spurts are particles with gravity that fall back into the coffee and make it slosh, the puffs of steam are a white body over a blue grey edge (on white, steam shows by its shadow) and the lid turns on its hinge with a bounce.

Those who cannot see, and the demo

The pot is a role=progressbar with aria-valuenow and aria-valuetext updated at most every 0.6 seconds, aria-busy while it works and an aria-live line for the start, the end and the download. The button stays the same element in every state, so keyboard focus is never lost; Brew again hands it back to the button as it goes. Clicks from a script (detail 0, the library preview’s) never download: after 2.5 seconds of Report ready they brew again, so the thumbnail runs by itself.

Values to change

NameFileDefaultWhat it changes
SECONDSscript.js3.6How long the demo’s export takes, in seconds, without the gas lighting up and the sputter at the end (a real one follows the server’s work).
STEPSscript.js[[0.2, 0.9], [0, 0.45], [0.47, 1], …]The export in fits and starts: for each step how far it gets (from 0 to 1) and how much of the time it takes; a step that goes no further than the last one is a pause.
JITTERscript.js0.25How much the steps’ weights change from one run to the next: 0 always the same. The length stays SECONDS.
HEATscript.js0.6The seconds between lighting the gas and the coffee reaching the top of the chimney.
SPURTSscript.js3The spurts of foam in the sputter at the end, each with its puff of steam and the lid rattling.
FLAMEscript.js15The flames’ height, in drawing units (the pot is about 200 tall); taller ones are pressed flat under the pot.
PORTSscript.js18The burner’s ports, that is how many flames there are round the ring.
GRAVITYscript.js320The gravity on the drops and the spurts, in drawing units per second squared.
WAVEscript.js[90, 2.4]The surface of the coffee and the water: how fast a ripple runs (units a second) and how quickly it dies down.
LABELSscript.js{ busy: 'Exporting…', done: 'Download', saved: 'Downloaded' }The button’s words while it works, at the end and once downloaded; the one at rest, Export report, is changed in index.html.
WORDSscript.js{ busy: 'Brewing your report…', done: 'Report ready' }The line under the pot while it works (followed by the percentage) and at the end; the one at rest, Ready to export, is changed in index.html.

Try them in the Playground

When to use it

For a wait of a few seconds that ends with something to take away: exporting a report or a PDF, preparing an archive to download, generating an invoice, a backup. It suits a product with a warm, crafted or Italian tone, or where the wait can be told as «we are making it for you»; the cut-away pot says how far along things are even without reading the number. For a very short wait, or one that does not end with something in hand, it is too much.

On phones

The component is 360 pixels wide and on a phone takes the width of the screen less 16 pixels a side (358 at 390); the pot stays 240 wide and the drawing is vector, so it stays sharp at any density, and the two canvases paint at the screen’s real density, up to twice. The drawing’s layers reach above the pot for the steam without scrolling the page sideways. The buttons are pills 44 tall: under a finger they squash and spring back; the pill that swells, the words that widen and the igniter’s sparks on the way past are there only with the mouse (or the keyboard, for the sparks).

With reduced motion

The flame fades in and out and does not flicker, no sparks, no drops, bubbles, foam, spurts or steam, the lid does not rattle and the surfaces stay flat. The coffee still climbs the chimney and fills the chamber and the water still goes down, with the percentage, because they are what says how far along things are; the stream down the chimney stays still and thin. The words change with a fade and the tick appears without drawing itself.

Pitfalls

  • Cut exactly on its axis, the pot showed only half the chimney and the coffee climbing it was a thread four pixels wide: the cut is moved 14 units left of the axis, so the whole chimney shows with both its sides.
  • The streams down the chimney, as thick and dark as the coffee inside it, turned the chimney into a brown pillar: they are now a thin, paler film, 1.6 units at most, with a line of light on the edge, and the hatched walls stay visible between the coffee inside and the coffee outside.
  • Steam on white: white does not show, grey looks like smoke. Each puff is a white body over a soft blue grey edge, and it reads by its shadow.
  • The wave surface never quite stopped (ripples of a hundredth of a pixel were left) and the canvas was painted again for nine seconds after the end: below 0.04 units the surface rests and the loop stops drawing.
  • Two blur filters with the same id in the page’s two SVGs: url(#…) always takes the first, and the valve’s shadow came out as blurred as the stove’s. They now have different names.
  • The status line, asked for every frame, started its fade again before it had finished: it now remembers the words on their way and does not start again for the same ones.
  • The flame’s blue reflection on the boiler’s bottom was twenty units tall and looked like paint: it is now a nine unit fade on the bevel.
  • The library preview clicks the marked button every 2.8 seconds, and as soon as it finished it would have pressed Download: clicks from a script (detail 0) never download and, after 2.5 seconds of Report ready, brew again.
  • Right after the tap «Ready to export 0%» could be read for a moment: the percentage fades in only once the line has changed.
  • The faded button while it works looked like a grey smudge in the poster: it now steps back into the quiet style, transparent with a ring, like the button next to it.

Libraries

GSAP 3.15.0, Bricolage Grotesque (font variabile) 5.3.0.

Compressed with gzip, the three demo files weigh 22 KB; the libraries: GSAP 28 KB.

Testing

Tested on 7 October 2026

  • Desktop: Done
  • Phone: Done
  • Reduced motion: Done
  • Safari on iPhone: To do

License

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.

All components