
The slide-to-confirm button
Buttons, Physics, Transitions
NewFree
The office Sign in with a badge: an ID card hanging on the cord of a spring reel over the pill, and the pill is the reader, with a slot along its top edge. At a click the badge is pulled down, goes into the slot behind the front of the pill, the magnetic stripe runs all the way through with a line of light under it, the reader answers Signing in… and then Signed in · Rui Costa; let go, the reel winds the cord back in and the badge goes up swinging. Sign out dips it into the reader, it comes out and hangs again. The badge can also be grabbed and swiped by hand.
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 badge swipe button</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/mona-sans@5.3.0/wdth.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<main class="stage">
<!-- the badge swipe button: the Sign in of an office, a studio or a lab. An ID badge hangs on a spring reel over the
pill, and the pill is the reader: a slot runs along its top edge. A click pulls the badge down, swipes it
through the slot and lets it go: the reel winds the cord back in and the badge swings. Signing out dips the
badge into the reader and it comes out and hangs again. The badge can also be grabbed and swiped by hand -->
<div class="swipe" data-swipe>
<!-- the reel, the cord and the badge, drawn by the script, between the back of the slot and the front of the pill -->
<canvas class="swipe__rig" aria-hidden="true" data-rig></canvas>
<span class="swipe__grip" aria-hidden="true" data-grip></span>
<button class="swipe__btn" type="button" data-btn data-autoclic>
<span class="swipe__back" aria-hidden="true"></span>
<span class="swipe__front" aria-hidden="true"></span>
<span class="swipe__faces">
<span class="swipe__face" data-face="rest">
<span class="swipe__word" data-wide="Sign in" data-rest-text>Sign in</span>
</span>
<span class="swipe__face swipe__face--busy" data-face="busy" aria-hidden="true">
<span class="swipe__shine" data-busy-text>Signing in…</span>
</span>
<span class="swipe__face swipe__face--done" data-face="done" aria-hidden="true">
<span class="swipe__who"><span data-done-text>Signed in</span> · <b data-name-text>Rui Costa</b></span>
<span class="swipe__out" data-out-text>Sign out</span>
</span>
<span class="swipe__face swipe__face--busy" data-face="gone" aria-hidden="true">
<span class="swipe__gone" data-gone-text>Signed out</span>
</span>
</span>
</button>
<p class="sr" aria-live="polite" data-live></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.
27 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 badge swipe button” from Animorio and fit it into my siteThe pill is two layers: the back of the slot, dark, behind the canvas, and the front, cut 10 pixels under the edge with clip-path, in front of it. The button has no z-index of its own, so the canvas with the badge sits in between: when the badge goes down into the slot it disappears behind the front, and it never covers the words.
The cord is a chain of twelve points: at each step gravity and the air move the points, then ten rounds of constraints put the links right, which can go slack but never stretch, and the speed comes from where the points ended up. The badge is a rigid body hanging from the last point: the clip and its middle, at a fixed distance, so it swings like a real pendulum.
The cord's length changes: when the hand pulls, the reel pays out all the cord it needs; let go, the spring winds it in at the speed REEL, braking on the last stretch as a real reel does. The badge is pulled up, the cord goes slack and it drops back and swings. The reel's face turns with the cord going in and out.
During the swipe the clip and the badge's middle follow a hand moved by a GSAP timeline: straight down, into the slot, all along the slot, out. Let go, the badge keeps the speed the hand gave it and gets a small twist on its strap, a spring of its own that narrows it as if it turned.
Out of the hand the cord and the badge do not go through the pill: the badge's lowest corner rests on its edge and slides, and the badge cannot swing over the reel. Dragged by hand, the badge goes into the pill only through the slot and only as deep as it is; the reader counts how much of the slot it has run through.
| Name | File | Default | What it changes |
|---|---|---|---|
LABEL | script.js | 'Sign in' | The words at rest. |
BUSY | script.js | 'Signing in…' | The words while the reader reads the badge. |
DONE | script.js | 'Signed in' | The words once in, before the name. |
PERSON | script.js | 'Rui Costa' | The name on the badge and in the words (invented: nothing is sent anywhere). |
ROLE | script.js | 'Studio' | The small word under the name, on the badge. |
LOGOUT | script.js | 'Sign out' | The little pill that signs out. |
LEAVING | script.js | 'Signing out…' | The words while it signs out. |
GONE | script.js | 'Signed out' | The words once out, before Sign in comes back. |
SWIPE | script.js | 0.6 | The seconds the swipe through the slot takes. |
GRAVITY | script.js | 2200 | How hard the badge falls, in pixels a second squared. |
REEL | script.js | 420 | How fast the reel winds the cord back in, in pixels a second. |
AIR | script.js | 1.1 | How much the air slows the swings: 0.2 it swings a long time, 4 it hardly swings. |
For the sign in of a work app: an intranet, a studio, a coworking space, a lab, an office dashboard. It stands alone on a light background; on a real site the call that really signs in goes where the swipe is, and the name comes from the account.
The pill fits the screen (at most the screen's width less 32 pixels) and the slot with it; the badge keeps its size. A tap on the pill makes the swipe; the badge can be grabbed with a finger too, and while it is held the page does not scroll.
No swings and no swiping: the badge fades out where it hangs and fades in already in the slot, still, with the line of light fading in; then it fades out and in again hanging. The words change with a fade and the pill does not swell.
GSAP 3.15.0, Mona Sans (font variabile) 5.3.0.
Compressed with gzip, the three demo files weigh 13 KB; the libraries: GSAP 28 KB.
Tested on 9 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.