
The time wheel
Pickers, 3D, Physics
NewFree
A site's menu as a steel filing cabinet in 3D: the items are drawers that come out on a spring as you pass; the chosen one runs out to its stop and the folders of the sub-items rise one after the other, their tabs in a staircase. Choosing another drawer, the open one slams shut and the cabinet jolts.
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 filing drawer menu</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/familjen-grotesk@5.3.0/index.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource/courier-prime@5.3.0/index.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource/courier-prime@5.3.0/700.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<main class="stage">
<!-- the menu as a filing cabinet: each item is a drawer in 3D. Under the pointer a drawer comes out a little on a
spring; pressed, it runs out on its rails and its folders rise one after the other, their tabs in a staircase.
The cabinet's shell, the dark holes and the inside of the drawers are drawn by the script -->
<nav class="cab" aria-label="Archive" data-cab>
<div class="cab__scene" data-scene>
<div class="cab__body" data-body>
<ul class="cab__drawers">
<li class="drawer" style="--tint: #e0603f" data-drawer>
<button class="drawer__front" type="button" aria-expanded="false" aria-controls="drawer-projects" data-front data-autoclic>
<span class="drawer__card"><span class="drawer__name">Projects</span><span class="drawer__range">A–F</span></span>
<span class="drawer__pull" aria-hidden="true"></span>
</button>
<ul class="drawer__folders" id="drawer-projects" aria-label="Projects" data-folders>
<li><a class="folder" href="#" data-folder aria-current="page"><span class="folder__tab">Residential</span><span class="folder__note">32 houses, 1998–2026</span></a></li>
<li><a class="folder" href="#" data-folder><span class="folder__tab">Workplace</span><span class="folder__note">Offices and studios</span></a></li>
<li><a class="folder" href="#" data-folder><span class="folder__tab">Hospitality</span><span class="folder__note">Hotels, two harbour baths</span></a></li>
<li><a class="folder" href="#" data-folder><span class="folder__tab">Unbuilt</span><span class="folder__note">Competitions we lost</span></a></li>
</ul>
</li>
<li class="drawer" style="--tint: #3f6fb0" data-drawer>
<button class="drawer__front" type="button" aria-expanded="false" aria-controls="drawer-studio" data-front data-autoclic>
<span class="drawer__card"><span class="drawer__name">Studio</span><span class="drawer__range">G–L</span></span>
<span class="drawer__pull" aria-hidden="true"></span>
</button>
<ul class="drawer__folders" id="drawer-studio" aria-label="Studio" data-folders>
<li><a class="folder" href="#" data-folder><span class="folder__tab">About us</span><span class="folder__note">Twelve people, one table</span></a></li>
<li><a class="folder" href="#" data-folder><span class="folder__tab">People</span><span class="folder__note">Partners and team</span></a></li>
<li><a class="folder" href="#" data-folder><span class="folder__tab">Awards</span><span class="folder__note">From Aalto to Mies</span></a></li>
<li><a class="folder" href="#" data-folder><span class="folder__tab">Careers</span><span class="folder__note">Two places open</span></a></li>
</ul>
</li>
<li class="drawer" style="--tint: #d49b25" data-drawer>
<button class="drawer__front" type="button" aria-expanded="false" aria-controls="drawer-journal" data-front data-autoclic>
<span class="drawer__card"><span class="drawer__name">Journal</span><span class="drawer__range">M–R</span></span>
<span class="drawer__pull" aria-hidden="true"></span>
</button>
<ul class="drawer__folders" id="drawer-journal" aria-label="Journal" data-folders>
<li><a class="folder" href="#" data-folder><span class="folder__tab">Essays</span><span class="folder__note">On brick, light and time</span></a></li>
<li><a class="folder" href="#" data-folder><span class="folder__tab">On site</span><span class="folder__note">Notes from the build</span></a></li>
<li><a class="folder" href="#" data-folder><span class="folder__tab">Press</span><span class="folder__note">What others wrote</span></a></li>
</ul>
</li>
<li class="drawer" style="--tint: #8a5a9e" data-drawer>
<button class="drawer__front" type="button" aria-expanded="false" aria-controls="drawer-contact" data-front data-autoclic>
<span class="drawer__card"><span class="drawer__name">Contact</span><span class="drawer__range">S–Z</span></span>
<span class="drawer__pull" aria-hidden="true"></span>
</button>
<ul class="drawer__folders" id="drawer-contact" aria-label="Contact" data-folders>
<li><a class="folder" href="#" data-folder><span class="folder__tab">Visit</span><span class="folder__note">By appointment</span></a></li>
<li><a class="folder" href="#" data-folder><span class="folder__tab">Write to us</span><span class="folder__note">Replies within a day</span></a></li>
<li><a class="folder" href="#" data-folder><span class="folder__tab">Newsletter</span><span class="folder__note">Four letters a year</span></a></li>
</ul>
</li>
</ul>
</div>
</div>
</nav>
<p class="sr" aria-live="polite" data-live></p>
</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.
59 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 filing drawer menu” from Animorio and fit it into my siteEverything is CSS 3D with transform-style: preserve-3d. The script builds the flat faces it needs (top, side, the steel strips round the drawers, the plinth, the dark behind each slot with its floor and wall, each drawer's box) and puts them in place from their middle with a translate3d, turned 90 degrees when they lie flat or stand sideways. The drawer fronts are real buttons, the folders real links: everything stays clickable and reachable with the keyboard.
Each drawer has a position and a speed moved by a hand-written spring (SPRING), in 4 millisecond steps on GSAP's ticker, with the frame step capped at 1/30 of a second. The spring pulls past the stop, so the drawer arrives fast: at the two ends of the rails the position is clamped and the speed bounces back, damped. A knock on the closed stop jolts the cabinet (a spring of its own) and gives the other drawers a random push; one on the open stop makes the folders swing.
The folders stand in the box one behind the other. Opening, they rise in turn every STAGGER seconds, each STEP pixels higher than the one in front, on a spring of their own; the tabs move from left to right along the edge, measured once the typeface has arrived, so above the drawer you read a staircase of names. Each folder is also a pendulum around its bottom edge, pushed by the knocks.
The cabinet is turned to show its top and right side and scaled to the width of the screen. The view follows the pointer by a few degrees, and with a drawer open it tilts further down (TILT) and rises the more the lower the drawer is, so you see inside it and it stays in the frame.
The drawers are buttons with aria-expanded and aria-controls, the folders links with aria-current; the arrows go from drawer to drawer and from folder to folder, Esc closes and gives the focus back to the drawer, and a press outside the cabinet closes it. When a folder is chosen, an invisible line (aria-live) tells screen readers the new page, once.
| Name | File | Default | What it changes |
|---|---|---|---|
OUT | script.js | 150 | How far a drawer comes out when it opens, in pixels. |
PEEK | script.js | 20 | How far it comes out under the pointer. |
SPRING | script.js | [170, 0.5] | The drawers' spring: how stiff, and how much it is held back (1 = no bounce). |
STEP | script.js | 30 | How much higher each folder rises than the one in front of it. |
STAGGER | script.js | 0.07 | The seconds between one folder rising and the next. |
TILT | script.js | [-15, -27] | The angle you look down at the cabinet from: at rest, and into an open drawer. |
START | script.js | -1 | The drawer open when the page loads (-1: none). |
For the menu of a studio, an archive, a publisher, a museum or a portfolio with many sections and subsections: wherever the idea of an archive truly belongs and the menu can be the first thing you see, in the middle of the page or on an index page.
The cabinet shrinks to the width of the screen, leaving room for the drawer that comes out towards the left. Without a mouse there is no preview on passing: at a touch the drawer gives a little and opens; the folders are touched on their tab or their body.
No travel and no springs: a drawer is shut or already all the way out, with the view already tilted, and the folders appear in place with a fade; no jolts, no swinging and no tilting with the pointer.
GSAP 3.15.0, Familjen Grotesk (font variabile) 5.3.0, Courier Prime 5.3.0.
Compressed with gzip, the three demo files weigh 9.6 KB; the libraries: GSAP 28 KB.
Tested on 4 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.