
The cookie banner
Consent, Transitions, SVG, Physics
NewFree
An architecture studio’s projects in a file tree: a folder opens on a spring and its files slide out from under it, go a little too far and come back, while the branch lines are drawn again every frame. A file picked up and carried stays on the end of its branch, which turns green, follows it and hooks onto the folder under the hand; let go there, the branch reels it into its new place, let go anywhere else it pulls it back home.
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 file tree on a leash</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/host-grotesk@5.3.0/index.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<main class="stage">
<!-- an architecture studio's projects in a file tree: folders open on a spring, every branch line is drawn again
each frame from where the rows really are, and a file carried away stays on the end of its branch, which
hooks onto the folder under it and reels the file in when it is let go -->
<section class="explorer" aria-labelledby="explorer-title" data-explorer data-autoclic>
<header class="explorer__head">
<h2 class="explorer__title" id="explorer-title">Projects</h2>
<button class="explorer__tool" type="button" aria-label="Collapse all folders" title="Collapse all folders" data-collapse>
<svg viewBox="0 0 16 16" aria-hidden="true"><path d="M4.75 2.5L8 5.75l3.25-3.25M4.75 13.5L8 10.25l3.25 3.25"/></svg>
</button>
</header>
<div class="explorer__scroll" data-scroller>
<div class="canvas" data-canvas>
<svg class="lines" aria-hidden="true" focusable="false">
<path class="lines__band" data-band/>
<path class="lines__hole" data-hole/>
<path class="lines__guides" data-guides/>
<path class="lines__wire" data-wire/>
</svg>
<div class="tree" role="tree" aria-labelledby="explorer-title" aria-keyshortcuts="Control+X Control+V" data-tree></div>
</div>
</div>
<div class="explorer__foot" data-foot>
<div class="explorer__foot-in">
<p class="explorer__note" data-note></p>
<button class="explorer__undo" type="button" data-undo>Undo</button>
</div>
</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.
45 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 file tree on a leash” from Animorio and fit it into my siteEvery row is positioned absolutely by one formula: each row has a slot as tall as a row times how open its folders are (a number from 0 to 1, and a little more when the spring overshoots) and times how much it is there itself; the slots are stacked from the top and the row sits at the bottom of its slot, clipped with clip-path: inset. So a folder opening lets its files slide out from under it, folders inside open with it, a file arriving opens its place and one leaving leaves a gap that closes, and no row ever overlaps another.
Each folder’s opening is a damped spring (OPEN_SPRING opening, CLOSE_SPRING closing) worked out on GSAP’s ticker in steps of 1/240 of a second, with the frame’s step capped at 1/30; its speed is kept, so a folder clicked again halfway goes back without a jerk. The chevron turns 90 degrees times the opening, so it overshoots too. The rows that cannot be seen get visibility: hidden, so Tab and screen readers do not find them; when nothing moves the loop stops.
A single SVG path under the rows, rebuilt from the slots every frame: for every open folder a trunk under its chevron and for every row a twig with a 6 pixel bend (a quadratic), as long as the row is out, stopping a pixel before the row’s sheet: the sheet of the row chosen starts there, and the branch holds it.
Picked up (after 4 pixels with the mouse, after PRESS seconds still with a finger), a file’s row leaves the formula and follows the hand with translate3d; its slot stays open and dashed. The green branch runs from the root of the folder under the hand (the row’s folder, or the folder itself if it is its row) to the sheet, and the root slides from folder to folder on a spring (HOOK_SPRING). While a file is carried nothing in the tree moves, so the row under the hand is always the one aimed at: resting 0.14 seconds on a folder’s row, a spring draws the file in to hang over the row below with its sheet widened, and the branch fades when it has no room to bend; after HOLD seconds a closed folder opens by itself.
Let go over another folder, an empty gap takes the file’s place and closes, a place opens in the folder after the folders in order of name, and the new indent is made up for in the sideways offset in the same frame; then a two-dimensional spring (LAND_SPRING), started with the hand’s speed, takes the row into its place and the green branch fades onto the grey twig. Undo makes the same flight backwards. The tree follows the ARIA tree pattern with a roving tabindex (arrows, Home, End, right opens or goes in, left closes or goes up, Enter chooses or opens) and Ctrl+X, Ctrl+V move a file; a click from a script (the preview) carries a file into another project, undoes it, closes everything and opens the first folders again.
| Name | File | Default | What it changes |
|---|---|---|---|
OPEN_SPRING | script.js | [260, 0.6] | The spring of a folder opening: how stiff it is and how much it is held back (under 1 the files go a little past and come back). |
CLOSE_SPRING | script.js | [420, 1] | The spring of a folder closing. |
LAND_SPRING | script.js | [230, 0.74] | The spring taking a file let go to its place, on the end of its branch. |
HOOK_SPRING | script.js | [620, 0.9] | The spring of the branch’s root sliding from folder to folder under the file carried, and of the file going to hang under a folder. |
HOLD | script.js | 0.6 | The seconds over a closed folder, carrying a file, before it opens by itself. |
PRESS | script.js | 0.3 | On a touch screen, the seconds a file is held before it comes away. |
OPEN_AT_START | script.js | ['Riverside Pavilion', 'Riverside Pavilion/Drawings', 'Harbour Baths'] | The folders open at the start, with their path. |
TREE | script.js | [['Riverside Pavilion', […]], …] | The projects: a name and, for a folder, what is inside it. |
For the file explorer of an editor in the browser, a studio’s archive, a team’s documents, a CMS’s assets: anywhere things move from one folder to another.
Rows are 44 pixels tall and the panel is at most 336 wide; a tap chooses a file or opens a folder. To pick a file up it is held a moment (PRESS): the row darkens and then comes away, and until then a finger that moves scrolls the page; while the file is in hand the page stays still. The panel never goes over 560 pixels: beyond that the list scrolls inside, a thin line appears under the title and a file landing out of sight is brought into view.
Folders open and close at once and the rows appearing fade in; the file carried follows the hand, which is what moves it, but let go it goes straight to its place and fades in there, with no flight, the branch’s root does not slide and the folder gives no nod; the line at the bottom of the panel appears without growing.
GSAP 3.15.0, Host Grotesk (font variabile) 5.3.0.
Compressed with gzip, the three demo files weigh 16 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.