
The three-line menu
Menus, Transitions, Physics, Text
NewFree
A minimal date picker only one week tall: the whole month unfolds out of that week like a sheet folded in a concertina, one row after the other with a thin crease that shows while it turns, and once the day is chosen it folds back into its week; the blue disc of the chosen day travels between the numbers, stretching like a drop.
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 unfolding calendar</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/roboto-flex@5.3.0/full.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<main class="stage">
<!-- the picker: a strip with the week of the chosen day. The arrow on the right (or dragging the strip down) unfolds
the whole month out of that week, row after row like a folded sheet; choosing a day folds it back into its week.
The chosen day sits on a disc that travels between the days. The weeks and the days are drawn by the script -->
<div class="wk" data-picker data-autoclic>
<div class="wk__head">
<h2 class="wk__title" aria-live="polite"><span data-title></span></h2>
<div class="wk__ctrl">
<button class="wk__nav" type="button" aria-label="Previous week" data-prev><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M14.5 6 8.5 12l6 6"/></svg></button>
<button class="wk__nav" type="button" aria-label="Next week" data-next><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M9.5 6l6 6-6 6"/></svg></button>
<button class="wk__toggle" type="button" aria-expanded="false" aria-controls="wk-days" aria-label="Show the whole month" data-toggle><svg viewBox="0 0 24 24" aria-hidden="true" data-chevron><path d="M6 9.5l6 6 6-6"/></svg></button>
</div>
</div>
<div class="wk__week" aria-hidden="true" data-week></div>
<div class="wk__body" id="wk-days" data-body>
<span class="wk__disc" aria-hidden="true" data-disc></span>
<div class="wk__rows" data-rows></div>
</div>
<span class="wk__grab" aria-hidden="true" data-grab><span></span></span>
<div class="wk__foot">
<p class="wk__day" aria-hidden="true" data-day></p>
<p class="wk__date" aria-hidden="true"><span class="wk__full" data-full></span><span class="wk__rel" data-rel></span></p>
</div>
<p class="sr" role="status" aria-live="polite" data-said></p>
</div>
</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.
17 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 unfolding calendar” from Animorio and fit it into my siteThe script draws the weeks of the month (four to six) and each one is two layers: the row, as tall as the part that is unfolded, and its face with the seven days, always one week tall. The face of the weeks above the chosen one is pinned to the bottom of its row and turns on its lower edge; the face of the weeks below is pinned to the top and turns on its upper edge. So every week always folds towards the week of the chosen day.
The whole fold is one number on a spring, from 0 (folded) to 1 (open), with FOLD and FOLD_DAMPING. Each week, d rows away from the chosen one, unfolds in its own stretch of that number, later the further away it is (STAGGER). From there come the angle (rotateX with perspective) and the height of the row, which is the height of the face times the cosine of the angle: it is how much of a turned face really shows, so the page below moves exactly as the sheet opens. Past 1, when the spring overshoots, the weeks already flat turn a few degrees the other way and come back.
Dragging the week (or the short line) up or down makes the number of the fold follow the hand, with a little give past both ends; letting go hands it back to the spring with the speed of the hand, so a flick opens or closes it even halfway. A sideways swipe on the folded strip turns the week. A drag doesn’t count as a click on a day.
The blue disc sits under the numbers and is moved by its own spring (DISC) towards the middle of the chosen day, measured on every frame from the real positions of the rows, so it stays tied to its day while the month opens and closes too. It stretches along its speed (STRETCH) and narrows across it, like a drop; the numbers under it turn white and gain weight, the ones it crosses on its way too.
With the month folded, changing week lays a copy of the old strip over the new one: GSAP turns the old days away forwards and turns the new ones in, one after the other (TURN), with a small bounce; the disc feels the knock and dips for a moment. If the new week is in another month, the month underneath is drawn again without it showing.
The weekday is set in Roboto Flex, whose width goes from 25 to 151 and optical size up to 144. Each letter is a span with two variables, --w for the width and --g for the weight: the old ones go to 25 and vanish, the new ones arrive from 25 to a little past 100 and come back, one after the other, gaining weight. The month at the top narrows and widens again when it changes, too.
| Name | File | Default | What it changes |
|---|---|---|---|
WEEK_START | script.js | 1 | The first day of the week: 1 Monday, 0 Sunday. |
FOLD | script.js | 2.2 | How quickly the month unfolds and folds back, in hertz. |
FOLD_DAMPING | script.js | 0.66 | The damping of the fold: lower, the weeks swing further past flat before they settle. |
STAGGER | script.js | 0.45 | How far behind the week before it each week unfolds (0 = all together). |
DISC | script.js | 4.4 | How quickly the disc travels to the new day, in hertz. |
STRETCH | script.js | 0.3 | How much the disc stretches as it travels (0 = it stays round). |
TURN | script.js | [0.5, 0.034] | The week turning over: the seconds of each day, and the gap between one day and the next. |
AUTO_FOLD | script.js | true | Choosing a day in the open month folds it back into that day’s week. |
Wherever a single day is chosen and space is short: booking a table or a class, the delivery day in a cart, an app’s agenda, the date of a show. At rest it takes one row and the month opens only when needed.
Below 480 pixels the cells narrow to fit the width of the screen and the written day gets a little smaller. With a finger you drag the week down to open the month and up to close it, with the same spring; a sideways swipe changes week, like the arrows.
No folds, no springs and no turns: the month fades in and out, the disc lands on the day at once with a fade, the new week and the new month replace the old ones with a fade, and the written day changes with a dissolve.
GSAP 3.15.0, Roboto Flex (font variabile, assi wght, wdth e opsz) 5.3.0.
Compressed with gzip, the three demo files weigh 13 KB; the libraries: GSAP 28 KB.
Tested on 18 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.