Skip to content
animorio
IT
All components

The unfolding calendar

Calendars, Transitions, Physics, TextGSAPAdvancedCompressed weight: Demo 13 KBGSAP 28 KBFreeDownload the zip

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.

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">
  <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>

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.

17 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 unfolding calendar” from Animorio and fit it into my site

What it does

On a white background, at the top the month, the two arrows and a round button with a down arrow; below, the names of the days and a single row: the week of the chosen day, with its number white on a blue disc. Further down a short line to take with a finger and, after a hairline, the weekday written large (Tuesday), the full date and how far away it is (In 2 days). The round button, or dragging the week down, unfolds the month: the weeks above and below turn on the edge that joins them to the chosen one, the near ones first and then the far ones, like a sheet folded in a concertina opening up, with the crease showing as a hairline and a breath of shadow; once flat they go a couple of degrees past and settle. Choosing a day of the month sends the disc over to it on a spring, stretched the way it runs, and the numbers it crosses turn white as it passes; then the month folds back into the new week. With the month folded the arrows (and a sideways swipe) turn the strip to the next or the previous week, one day after the other like a split-flap board; with the month open they change month. The day written below changes letter by letter: the old letters narrow on the width axis and vanish, the new ones widen a little past their size and gain weight. Past days are pale and can’t be chosen, today has a blue number.

How it works

The weeks of a month

The 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.

One number for the fold

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.

The hand on the fold

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 travelling disc

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.

The week turning over

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 day written large

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.

Values to change

NameFileDefaultWhat it changes
WEEK_STARTscript.js1The first day of the week: 1 Monday, 0 Sunday.
FOLDscript.js2.2How quickly the month unfolds and folds back, in hertz.
FOLD_DAMPINGscript.js0.66The damping of the fold: lower, the weeks swing further past flat before they settle.
STAGGERscript.js0.45How far behind the week before it each week unfolds (0 = all together).
DISCscript.js4.4How quickly the disc travels to the new day, in hertz.
STRETCHscript.js0.3How much the disc stretches as it travels (0 = it stays round).
TURNscript.js[0.5, 0.034]The week turning over: the seconds of each day, and the gap between one day and the next.
AUTO_FOLDscript.jstrueChoosing a day in the open month folds it back into that day’s week.

Try them in the Playground

When to use it

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.

On phones

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.

With reduced motion

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.

Pitfalls

  • The round button’s arrow, turned by the script with the fold, rotated around its top left corner and left the circle: the svg needs transform-origin at its centre.
  • The number turned white with a colour transition: when the disc left it stayed almost white on white for a moment. Now it turns white only when the disc is over it, measured on every frame, and the colour changes almost at once.
  • The width of the month at the top didn’t change: the --tw variable has to be tweened on the title, which has the font-variation-settings, not on the span inside it, which inherits the value already worked out.
  • In the preview’s tour, at the end of a month, there was no next week in the same month and the tour skipped half the states: now it picks a far day by itself and whether to turn to the next week or the one before, and the round ends where it began.
  • With reduced motion the two weekday words faded one over the other and read as a mess: now the old one is gone before the new one arrives.
  • The preview’s tour lives in a GSAP timeline: so the video records the whole round, and a real hand stops it at once.

Libraries

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.

Testing

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