Skip to content
animorio
IT
All components

The publishing origami

Loading, 3D, TransitionsCanvas, GSAPAdvancedCompressed weight: Demo 17 KBGSAP 28 KBFreeDownload the zip

The publish panel of a blog, with the article as a square sheet of two-tone origami paper: every phase of the publishing is a group of real folds, each drawn first as the dashed line of an origami diagram, and the square becomes a kite, then a swan with a neck, a head and a tail. When the article is live the swan opens its wings, takes off with a few beats and lands. If the upload fails the flap that was folding falls open again and its line stays red until Retry folds it again.

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 publishing origami</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/instrument-sans@5.3.0/wdth.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <main class="stage">
    <!-- the publish panel of a blog: the article is a square of two-tone origami paper. Every phase of the publishing
         (build, optimize, upload, publish) is a group of folds, each one drawn first as a dashed line like in an
         origami diagram; the square becomes a kite, then a long body, then a bird with a neck, a head and a tail.
         When the article is live the bird opens its wings, takes off with a few beats and lands again.
         The paper is painted by script.js on the canvas; the words, the phase bars and the button are HTML -->
    <section class="pub" aria-labelledby="pub-title" data-publish>
      <div class="pub__head">
        <div class="pub__words">
          <h2 class="pub__title" id="pub-title">Notes on Folding</h2>
          <p class="pub__meta"><span class="pub__swap" data-meta>Draft · saved 2 min ago</span></p>
        </div>
        <p class="pub__figure" aria-hidden="true">
          <span class="pub__pct" data-pct>1,240 words</span>
          <span class="pub__live" data-live-badge>
            <svg class="pub__tick" viewBox="0 0 24 24"><path d="M5.5 12.6l4.1 4.1L18.6 7.4" pathLength="1"/></svg>
            <span>Live</span>
          </span>
        </p>
      </div>
      <div class="pub__paper" aria-hidden="true" data-paper>
        <canvas class="pub__canvas" data-canvas></canvas>
      </div>
      <div class="pub__phases" role="progressbar" aria-labelledby="pub-title" aria-valuemin="0" aria-valuemax="100"
           aria-valuenow="0" aria-valuetext="Not published yet" data-bar>
        <div class="pub__phase" data-phase><span class="pub__name">Build</span><span class="pub__track"><span class="pub__fill"></span></span></div>
        <div class="pub__phase" data-phase><span class="pub__name">Optimize</span><span class="pub__track"><span class="pub__fill"></span></span></div>
        <div class="pub__phase" data-phase><span class="pub__name">Upload</span><span class="pub__track"><span class="pub__fill"></span></span></div>
        <div class="pub__phase" data-phase><span class="pub__name">Publish</span><span class="pub__track"><span class="pub__fill"></span></span></div>
      </div>
      <div class="pub__foot">
        <p class="pub__site"><span class="pub__swap" data-site>fieldnotes.blog/notes-on-folding</span></p>
        <button class="pill" type="button" data-action data-autoclic><span class="pill__label" data-label>Publish</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.

38 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 publishing origami” from Animorio and fit it into my site

What it does

On a white background, alone in the middle, a paper-coloured panel with round corners: at the top Notes on Folding and Draft · saved 2 min ago, on the right 1,240 words; in the middle a square ink blue sheet lying as a diamond, seen a little from above as on a desk, with its shadow; below, the four phases Build, Optimize, Upload and Publish with a small bar each, the article’s address and the black Publish button. Pointing at the button, the first dashed line is drawn on the sheet and its corner lifts a little, ready to fold. Pressed, the publishing starts: before every fold its line is drawn as in an origami diagram (dashed for a valley fold, dash and dot for a mountain fold), then the flap comes off the sheet, turns in 3D round the line, darkens as it rises, shows the paper’s other side, coral, and lies down on the other side; a glint of light runs along the new crease. In Build the two sides are folded to the middle and the sheet becomes a kite; in Optimize the kite is folded in half, turns on its side with a little bounce and the wide point becomes the tail; in Upload the long point is turned inside out upwards and becomes the neck; in Publish the head and beak are turned out of the top of the neck. Meanwhile the line names the phase (Building 24 pages…, Optimizing 61 images…, Uploading 38 files…, Going live…), the percentage climbs, the phase under way is set wider and its bar fills; the button becomes Cancel, pale and outlined. At the end a green tick is drawn with Live in place of the percentage, the line says Live on fieldnotes.blog · just now and the swan crouches, opens its wings, rises with a few beats turning to show them, glides and lands with a little settle, its wings just open. Publish again unfolds it fold by fold, the last one first, back to the square, and the publishing starts over. Cancel while it works does the same and goes back to the sheet: Cancelled · draft kept. One time in two, in the demo, the upload fails: the neck’s flap rises, hesitates and falls open again with a bounce, its line stays on the sheet dashed in red, the Upload phase turns red and the line says Upload failed · 3 files timed out; Retry, in blue, gives the line its colour back and the neck folds again.

How it works

The paper is made of facets

The sheet is a list of convex polygons, each with its outline in the paper’s own coordinates (the square from −0.5 to 0.5), the affine map that brings it to where it lies now and its height in the stack. At the start there is a single facet. So a facet always knows which part of the paper it is, and which of its sides are the sheet’s cut edge and which are creases.

A real fold

A fold is a line (a point and a direction), the side that moves and the kind: valley, mountain or reverse. Every facet the line crosses is cut in two (a convex polygon clipped by a half plane), and the parts on the moving side are reflected: their map gets the mirror in the line, x′ = x − 2((x − p)·n)n. In a valley fold the flap ends on top of the stack with the order of its layers reversed, in a mountain fold at the bottom; in a reverse fold the point ends between the layers, as in a real neck. All the folds are worked out once at the start: for each one the paper cut before the fold and the paper after are kept.

The flap turns in 3D

During the fold every point of the flap, at a distance d from the line, lies at foot + n·d·cos θ and d·sin θ high, with θ from 0 to 180 degrees; its height in the stack meanwhile goes from the old one to the new one. Everything is projected in perspective after turning the scene: the sheet is seen a little from above, and while the flap stands up the camera leans a little, so that you see it lifted off the paper and not just shortened. The facets are painted from the lowest to the highest, measured in the paper’s frame and not after the turn.

Light, the other side, shadows and creases of light

Which side of the paper shows comes from the winding of the projected outline: if the reflection has reversed it you see the back, coral instead of blue. The facet’s normal, worked out from its corners in 3D, gives the light coming from the top left; every facet casts a shadow that grows with its height, and the whole sheet a blurred shadow on the panel, drawn off the canvas so that only the shadow lands. The sides that are creases are traced with a pale line, the cut edges with a dark one; a glint runs along every new crease, and a very faint grain of fibres covers the paper.

The diagram, the error and the flight

Before every fold its line is drawn in the style of origami diagrams, pale where it runs on the paper and dark outside it, clipped to the sheet’s outline. If the upload fails the flap stops halfway and falls back with elastic.out, and the line turns red. The wings are the kite’s two flaps, hinged on the back: in flight they turn round that hinge in opposite directions, between 30 and 118 degrees, while the camera turns and drops to show them. Unfolding is the same thing backwards: every fold from 180 to 0 degrees, the last one first.

For those who cannot see it and those who want no motion

The four phases are a role=progressbar with aria-valuenow and an aria-valuetext naming the phase; the panel has aria-busy while it works and an aria-live line says when the publishing starts, fails, is cancelled and when the article is live. The button changes its word (Publish, Cancel, Retry, Publish again) and takes the new width with a little bounce; a click from a script, the library preview’s, never cancels and publishes again only after Live has shown for two and a half seconds.

Values to change

NameFileDefaultWhat it changes
SECONDSscript.js7.5How long the demo’s publishing takes, in seconds, before the swan flies: all the folds get shorter or longer together.
WORDSscript.js['Building 24 pages', 'Optimizing 61 images', …]What the line says during the four phases (the phases’ names under the sheet are in index.html).
SITEscript.jsfieldnotes.blog/notes-on-foldingThe article’s address; at the end the line says on which site it is live.
FAIL_EVERYscript.js2In the demo, one publishing in how many goes wrong (0 never).
FAIL_PHASEscript.js2The phase that goes wrong then: 0 Build, 1 Optimize, 2 Upload, 3 Publish. The flap that falls open is that phase’s first fold.
NECKscript.js0.62How long the swan’s neck is, in sides of the sheet.
BEATSscript.js3The wing beats when the swan takes off.
LIFTscript.js30How high it flies, in pixels.
TURNscript.js30How far it turns in flight to show its wings, in degrees.
GLINTscript.js0.75The glint that runs along every new crease: 0 none, 1 bright.

Try them in the Playground

When to use it

For a wait of a few seconds split into phases and with an outcome: publishing an article or a site, a deploy, an export that goes through several stages. The folds say «a flat thing taking shape one step at a time» well, and the flap that falls open shows at once where everything stopped; for a load of a moment it is too much.

On phones

The panel takes the screen’s width less 32 pixels (358 on a 390 screen) and stays 362 tall; the sheet scales to fit its room and the canvas paints at the screen’s real density, up to twice. The button is a pill 40 tall that squashes and springs back under a finger; the corner lifting ahead of time and the widening words are there only under the mouse.

With reduced motion

No turning flaps, leaning camera, glints or flight: the dashed lines still show, and at every fold the new sheet fades in over the old one, so the figure grows step by step and says how far along things are. The error leaves the flap open with the red line, the end shows the swan standing with its wings just open, and the new words fade in.

Pitfalls

  • Seen straight from above, a flap at 90 degrees is edge on and vanishes: the fold looked like a blind wiping across the sheet. The sheet is now seen a little from above, as on a desk, and while the flap stands up the camera leans a little.
  • The first wings were folds that raised the flaps above the back: they looked like a sail and hid the neck. The wings are now the kite’s two flaps, which are already hinged on the back, and they turn round that hinge.
  • With paper coral on one side and pink on the other the open wings had the body’s colour and did not read: the paper has two strong colours, ink blue and coral, and every wing beat flashes the other side.
  • Sorting the facets by depth after the camera’s turn, layers of the same stack swapped places depending on how far right or left they lay: the order now comes from the height in the paper’s frame, before the turn.
  • The dark dashed line vanished on the blue paper: it is now drawn twice with a clip, pale inside the sheet’s outline and dark outside it.
  • At rest the sheet already showed the crease of the first fold, because the paper cut for the coming fold was drawn: the cut paper is used only once the line starts drawing.
  • The publishing lasted nine seconds instead of seven and a half: the glint along every crease was queued on the timeline. The glint now runs on its own, and the timeline, measured once in a dry run, is sped up or slowed down to last SECONDS.
  • That dry run wrote its starting values into the real state, and at rest a dashed line showed for a moment: the dry run now works on a copy.
  • The preview’s click never published again: GSAP’s ticker time stops when there is nothing to animate, so the seconds since the end did not pass. They are now measured with performance.now.
  • For a moment 99% and Live showed on top of each other: Live arrives only once the percentage has gone.

Libraries

GSAP 3.15.0, Instrument Sans (font variabile) 5.3.0.

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

Testing

Tested on 8 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