Skip to content
animorio
IT
All components

The drone-drop toast

Notifications, Physics, TransitionsGSAP, CSS onlyAdvancedCompressed weight: Demo 12 KBGSAP 28 KBFreeDownload the zip

The order notifications of a home goods shop are brought by a small drone: it comes in from the side with the notification hanging from two cables, brakes while the notification swings, lowers it into its place, the cables go slack, the clips let go and the drone flies off reeling them in. Dismissed, another drone comes back for it, hooks the edge, takes the weight with a small dip and carries it away, while the next notification arrives.

The code

A folder that runs on its own: index.html, style.css, script.js and the libraries from a CDN. The React tab holds 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 drone-drop toast</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/geist@5.3.0/index.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <main class="stage">
    <!-- the order notifications of a home goods shop, brought by a small delivery drone. The drone flies in with the
         notification hanging from two cables, lowers it into its place, lets go and flies off reeling the cables in.
         Dismissed (the cross, Track, Esc), a drone comes back, hooks it and lifts it away, while the next one arrives;
         swiped sideways, it is thrown off. The notifications and the drones are made by script.js, from MESSAGES;
         the cables are chains of points worked out every frame, the notification is a rigid body hanging from them -->
    <div class="dock" data-dock>
      <section class="shelf" aria-label="Notifications" data-shelf></section>
      <svg class="sky" aria-hidden="true" data-sky>
        <defs>
          <linearGradient id="drone-shell" x1="0" y1="0" x2="0" y2="1">
            <stop offset="0" style="stop-color: var(--drone-light)"/>
            <stop offset="0.55" style="stop-color: var(--drone)"/>
            <stop offset="1" style="stop-color: var(--drone-dark)"/>
          </linearGradient>
          <linearGradient id="drone-disc" x1="0" y1="0" x2="1" y2="0">
            <stop offset="0" style="stop-color: var(--rotor); stop-opacity: 0"/>
            <stop offset="0.5" style="stop-color: var(--rotor); stop-opacity: 0.32"/>
            <stop offset="1" style="stop-color: var(--rotor); stop-opacity: 0"/>
          </linearGradient>
          <clipPath id="drone-body-clip">
            <rect x="-29" y="-13" width="58" height="23" rx="11.5"/>
          </clipPath>
        </defs>
        <g data-cables></g>
        <g data-drones></g>
      </svg>
      <p class="sr" role="status" aria-live="polite" aria-atomic="true" data-live></p>
    </div>
  </main>

  <template data-template>
    <article class="toast" inert>
      <svg class="toast__icon" viewBox="0 0 36 36" aria-hidden="true" data-icon></svg>
      <div class="toast__text">
        <p class="toast__title" data-title></p>
        <p class="toast__body" data-body></p>
      </div>
      <button class="toast__action" type="button" data-action></button>
      <button class="toast__close" type="button" aria-label="Dismiss notification" data-close data-autoclic>
        <svg viewBox="0 0 24 24" aria-hidden="true"><path d="M7 7l10 10M17 7L7 17"/></svg>
      </button>
    </article>
  </template>

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

43 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 drone-drop toast” from Animorio and fit it into my site

What it does

On a white background, alone in the middle, a white notification 70 pixels tall with a hairline edge and a soft shadow: a cardboard parcel with orange tape, Your order has shipped, Arrives Thursday, Oct 16, the dark Track button and the cross. It does not just appear: a graphite drone with an orange band brings it, seen from the front, with its propellers spinning into a blur. The drone comes in from the side already flying, with the notification hanging under it from two thin cables that end in two steel clips on its top edge; braking, it leans back and the notification swings forward, tilted, then less and less. Over its place the drone stops and pays the cables out: the notification goes down, touches the floor (one corner first, if it still swings), the cables go slack and lie on the edge, the clips let go and the notification slides the last pixel into its place while its shadow tightens. The drone reels the cables in, waving with their clips, climbs and leaves the other way, leaning into the acceleration. The cross, Track or Esc call a drone: it comes in from the other side with its clips dangling, lowers them onto the edge, hooks them, pulls the cables until they take the weight (and dips a little), lifts the notification and carries it away swinging; meanwhile the next notification comes in: Out for delivery, Delivered to your door, Return picked up, in turn. Dragged sideways with a finger or the mouse, the notification follows and leans a little; past a third of its width, or with a flick, it flies off turning and falls out of the page. When the page opens a first notification arrives by itself.

How it works

A rigid notification made of four points

The notification is a Verlet rigid body: its four corners are points with their position now and before, held together by six sticks (the four sides and the two diagonals). At every step gravity pulls them down and the constraints put them back, eight times; the centre and the angle come out of the points, and the real notification (an HTML element with its buttons) moves with a single transform. The physics step is never longer than 1/240 of a second, and a slow frame takes more of them.

Two cables pulling a point on the edge

Each cable is a one-way constraint: when the clip is further from the winch than the cable is long it is brought back, otherwise the cable is slack and does nothing. The clip holds a point on the top edge, between the two corners, so the correction is shared between the two corners by how close the point is to each (the weights (1 − a) and a, normalised). With the winches closer together than the clips the cables open into a trapezium: the notification hangs straight, but braking makes it swing and turn as well. The floor of its place stops the corners with friction, so it lands one corner first.

A drone chasing its target

GSAP does not move the drone: it moves its target (cruise, then braking, then the climb and the exit) and the length of the cables, with calls to hook and let go. The drone follows it on a lightly damped spring, so it lags, goes a little past and comes back; it leans as much as it accelerates, filtered, like a real quadcopter. The cables' pull drags it down, and when it takes the weight it dips a little. The swing is damped against the drone and not against the air, or in flight the notification would always trail behind, crooked.

The cables drawn are chains

What shows of a cable is a chain of fourteen points, hung from the winch and the clip, with segments a thirteenth of the cable's length: taut it becomes a line, slack it bends, free it dangles with the heavier clip, and reeled in it gathers under the drone. A slack cable rests on the edge of the place and never crosses the words. Every frame the chain becomes an SVG path with Bézier curves through the midpoints, and the clip turns along the cable (or square to the edge, while it holds).

The drone, drawn in SVG

The drone is an SVG group: the shell with a gradient from grey to almost black, the orange band clipped to the shell, the visor, the arms, the legs and the winches. Each propeller is a blurred disc (a gradient fading at the sides) with a blade on top that widens and narrows with the cosine of its angle, like a spinning blade seen edge on. The drawing loop stops by itself when nothing is flying any more.

Gestures, keyboard and reduced motion

While it flies the notification is inert; once down the buttons work, a role="status" line reads it and, if the focus was on the dismissed notification, it moves to the new one's cross. Esc dismisses it. A sideways drag picks its direction after six pixels (vertically the page scrolls); let go, a throw becomes the speed and turn of the four points, which fall freely. LIFE, when above zero, sends the drone by itself, but the wait stops under the pointer and with the focus inside.

Values to change

NameFileDefaultWhat it changes
FLYscript.js1.3The seconds the drone takes to fly in with a notification.
LOWERscript.js0.9The seconds it takes to lower the notification into its place.
COLLECTscript.js0.8The seconds a drone takes to come back for a dismissed notification.
CABLEscript.js120How long the cables are while the drone carries the notification, in pixels.
GRIPscript.js0.2Where the clips hold the top edge, from each end: 0.05 near the corners, 0.35 near the middle.
TILTscript.js1How far the drone leans into its flight: 0 upright, 2 a lot.
SWAYscript.js2How quickly a swing dies down: 0.3 it swings for long, 5 it barely swings.
LIFEscript.js0The seconds before a drone collects a notification by itself (0: it stays until dismissed).
FIRSTscript.js0.5The seconds before the first notification arrives.
MESSAGESscript.jsquattro, da Your order has shipped a Return picked upThe notifications, in turn: the parcel drawn (box, route, open, return), the title, the line under it and the button.

Try them in the Playground

When to use it

For the notifications of an online shop or a delivery app, where the message really is about a parcel: shipped, out for delivery, delivered, returned. One notification at a time, with a title and a line; arriving takes about three seconds, so it suits places where notifications are few and matter, not where they come in bursts. On a quieter site FLY can be shorter and SWAY higher.

On phones

The notification takes the width of the screen minus 32 pixels (358 at 390) and below 420 pixels the gaps and the text get a little narrower; the clips stay a fifth from each end, so the cables open a little less. The drones come in and leave at the edges of the screen. A sideways swipe throws it off; vertically the page scrolls as usual. The cross has a touch area bigger than the drawn one.

With reduced motion

No drones, no cables and no swinging: the notification fades in at its place and fades out, with the cross, with Track, with Esc or with a swipe, and the next notification fades in.

Pitfalls

  • The drone started from rest and its target jumped straight to full speed: the jolt turned the notification by almost 45 degrees, up above the drone. Now the drone comes in already at cruise speed, with the notification moving along with it, and brakes only over the last part of the flight.
  • With the target on power2.out the drone braked for the whole flight, and the notification stayed tilted by 25 degrees from start to end: a real flight is cruise and then braking.
  • Damping against the air kept the notification trailing behind during the flight. The swing is damped against the speed of the drone carrying it; in the air only a light drag is left for a thrown notification.
  • Lowered with some cable to spare, the slack chain of a cable fell in front of the notification and crossed the words. Now the cables go slack by a few pixels and every point of the chains rests on the top edge of the place, as on a table.
  • On the phone the drone taking the old notification away and the one bringing the new one passed within a few pixels of each other, the two notifications almost on top of one another: the new one sets off 0.7 seconds after the old one has got clear.
  • The preview's click also comes while the notification is flying: until it is down the notification is inert and the click does nothing, and the poster uses the preview's click (posterClic) so as not to wait for the end of the flight.

Libraries

GSAP 3.15.0, Geist (font variabile) 5.3.0.

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

Testing

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