Skip to content
animorio
IT
All components

The route tiles

Loading, SVG, TransitionsGSAPAdvancedCompressed weight: Demo 9.1 KBGSAP 28 KBFreeDownload the zip

A delivery app looking for a rider, shown as a grid of Truchet tiles: every tile holds two quarter circles joining its sides two by two, and a quarter turn changes which sides it joins. At rest the tiles are scrambled and no line gets from one side to the other. While it searches, the tiles near the front of the search are tried, flash and turn a quarter, and the right tile turns into place on a spring: the route lights up behind it, arc after arc, from the kitchen to the door. If no rider is near the route turns red and stops until Retry carries on; at the end the rider runs along the route, and Done scrambles the grid 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 route tiles</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/recursive@5.3.0/full.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <main class="stage">
    <!-- the route tiles: a food delivery app looking for a rider, and the search is a grid of Truchet tiles, each with two
         quarter arcs. Scrambled at rest; while it searches the tiles turn a quarter at a time until one path runs
         unbroken from the kitchen to the door, and the route lights up behind them. The tiles are built by script.js -->
    <section class="rt" aria-labelledby="rt-title" data-route>
      <div class="rt__head">
        <div class="rt__words">
          <h2 class="rt__title" id="rt-title"><span class="rt__swap" data-title>Your order</span></h2>
          <p class="rt__meta"><span class="rt__swap" data-meta>Osteria Lume · 2 items · €31.40</span></p>
        </div>
        <p class="rt__figure" aria-hidden="true">
          <span class="rt__pct" data-pct>0%</span>
          <svg class="rt__tick" viewBox="0 0 28 28" data-tick><path d="M6.5 14.8l5 5 10-11.4" pathLength="1"/></svg>
        </p>
      </div>

      <div class="rt__map" role="progressbar" aria-labelledby="rt-title" aria-valuemin="0" aria-valuemax="100"
           aria-valuenow="0" aria-valuetext="Not started" data-bar>
        <svg class="rt__svg" viewBox="0 0 408 208" aria-hidden="true" data-svg>
          <g data-tiles></g>
          <path class="rt__route" data-route-line/>
          <path class="rt__rider" data-rider/>
          <g class="rt__cap rt__cap--from" data-from>
            <rect x="-6" y="-6" width="12" height="12" rx="3"/>
          </g>
          <g class="rt__cap rt__cap--to" data-to>
            <path d="M-6.5 6.5V-1L0 -7l6.5 6V6.5z"/>
          </g>
        </svg>
      </div>

      <div class="rt__ends" aria-hidden="true">
        <span>Osteria Lume</span>
        <span>14 Via Sole</span>
      </div>

      <div class="rt__foot">
        <span class="rt__status"><span class="rt__swap" data-status>Paid · ready to send</span></span>
        <button class="pill" type="button" data-btn data-autoclic>
          <span class="pill__fill" aria-hidden="true"></span>
          <span class="pill__label" data-label>Find a rider</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.

31 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 route tiles” from Animorio and fit it into my site

What it does

On a black background, alone in the middle: at the top Your order and under it Osteria Lume · 2 items · €31.40, with 0% on the right; below, a grid of 9 by 5 invisible tiles, each with two dark grey quarter circles, that together make a maze of waves and circles; on the left, outside the grid, a small square with round corners (the kitchen), on the right a little house drawn as a hairline (the door), and under them their names Osteria Lume and 14 Via Sole. At the foot Paid · ready to send and the light pill Find a rider. Coming in, the tiles appear turning a quarter, in a diagonal wave. Press Find a rider and the kitchen’s square turns yellow and a yellow line comes out towards the grid; then, at every step, two or three tiles near the front are tried (they lighten and turn a quarter with a small bounce) and the right tile turns into place going a little past it and back, and the yellow route grows along its arc. The route snakes across the grid, curve after curve, to the door, while the percentage goes up and the pill becomes a ring that says Cancel, which puts the route out and scrambles the tiles. One time in two no rider is near: the route turns red, the tile where it stopped shakes, the title says No rider nearby yet in red and under it Your food is kept warm; Retry carries on. At the end the route reaches the door, the little house fills with yellow, a short white stroke, the rider, runs along the whole route from the kitchen to the door and the house gives a little hop, the percentage gives way to a green tick, the title says Rider on the way, under it Arrives in 18 min and at the foot Ada is at the kitchen. Done puts the route out and scrambles the tiles in a wave that starts at the door, back to the same maze as before.

How it works

Truchet tiles

Every tile is an SVG group with two quarter circles of half its side: turned 0 degrees it joins the top side to the left and the bottom to the right; turned a quarter it joins the top to the right and the bottom to the left. A half turn changes nothing, so its way round is the number of quarter turns modulo two, and GSAP turns the group round the middle of the tile with svgOrigin.

The route, found first

Entering a tile by one side, the route can only leave by one of the two sides next to it: it has to turn at every tile. The route is a walk that never goes through the same tile twice, found depth first with a seeded generator: it starts from the left in a random row, prefers the ways out to the right with a little chance, backs up when it is shut in, and only counts if it leaves by the right side after at least one and a half times the columns. Every tile of the route notes the way round it needs.

The scramble and the tries

At rest every tile of the route is turned the wrong way and the others at random, from the seed, so the grid lets nothing through. While searching, at every step, up to TRIES tiles near the front (at most two tiles away) light up and turn a quarter with a light back.out; then the route’s tile turns a quarter (or half, if it were already right) with a back.out of SPRING, going past and back.

One route, over the tiles

The lit route is a single SVG path, built once: a stretch from the kitchen, an A arc per tile (centred on the corner between the side it enters and the one it leaves, its direction from the cross product) and a stretch to the door. Every arc is π·r/2 long, so the lit length is the sum of the arcs of the tiles already in place, and stroke-dashoffset follows it on a tween. The rider is the same path with a single short dash, run along by stroke-dashoffset.

Scrambling the same

Going back to rest every tile turns one, two or three quarters back to its starting way round, in a wave that starts at the door: since a half turn does not change a tile, the maze comes back exactly as it was even though the angles differ, and the preview’s round starts over the same.

Values to change

NameFileDefaultWhat it changes
GRIDscript.js[9, 5]Columns and rows of tiles.
SECONDSscript.js6How many seconds the search takes in the demo.
TRIESscript.js2How many tiles near the front are tried before each tile of the route.
SPRINGscript.js2.4How far a tile turning into place overshoots.
SEEDscript.js5The route and the scramble: another number, another route.
MINUTESscript.js18How many minutes the rider will take, said at the end.
FAIL_EVERYscript.js2One search in how many finds no rider at first (0 never).
FAILscript.js0.58Where the search stalls, from 0 to 1.
PREVIEWscript.js1.4In the preview’s round: how many times faster.
LABELSscript.js['Find a rider', 'Cancel', 'Retry', 'Done']The words of the pill, state by state.
--routestyle.css#ffd23fThe colour of the route.
--tilestyle.css#34332fThe colour of the tiles’ arcs.

Try them in the Playground

When to use it

For finding a rider in a delivery or restaurant app, for working out a route in a shipping, taxi or maps app, for confirming an order with delivery, for any wait where something has to find its way from one point to another.

On phones

The panel takes the whole width less the margins and the grid, an SVG with its own viewBox, shrinks with it: the tiles are the same, a little smaller. The pill answers a touch as it does the mouse.

With reduced motion

The tiles do not turn: they fade out and back in already turned. The route still lights up tile after tile, because it is the progress, but without sliding; the rider does not run, the stalled tile does not shake and the words change without moving.

Pitfalls

  • A Truchet tile never goes straight: entering from the left it can only leave at the top or the bottom. A random walk heading right often got shut into a corner, so the route is found depth first with backtracking, with a limit on the tries and, if that is not enough, any walk that crosses the grid.
  • The tiles tried during the search were sometimes tiles of the route, which then turned the wrong way: now only tiles that are not part of the route are tried.
  • Going back to rest with a random turn the tiles ended in a different maze from the starting one, and the preview’s round did not start over the same: now every tile goes back to its starting way round, and the extra half turn of some is only movement.

Libraries

GSAP 3.15.0, Recursive (font variabile, assi MONO, CASL e wght) 5.3.0.

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

Testing

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