Skip to content
animorio
IT
All components

The brass toggle switch

Toggles, WebGL, 3D, PhysicsWebGL, GSAPAdvancedCompressed weight: Demo 16 KBGSAP 28 KBFreeDownload the zip

The Studio monitor setting of a recording app, and the switch is an old toggle from a studio console: a polished brass lever standing out of a threaded bushing, held by a hex nut to a plate of oxblood bakelite, with OFF and ON engraved and filled with paint. It is all drawn in 3D in a shader: clicked, a finger pushes the lever against its spring up to the dead centre, then the spring throws it over, it knocks its stop and bounces; the reflections run along the brass and its shadow sweeps the plate.

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 brass toggle switch</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/archivo@5.3.0/wdth.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <main class="stage">
    <!-- the Studio monitor setting of a recording app, and the switch is an old brass toggle on a plate of bakelite,
         the kind on a studio console: a bat handle lever in a threaded bushing with a hex nut, OFF and ON engraved
         and filled with paint. The lever is drawn in 3D, ray marched in a shader: flicked or dragged, it is pushed
         against its spring up to the dead centre, snaps over and knocks its stop with a little bounce, while the
         reflections run along the brass and its shadow sweeps across the plate -->
    <div class="tile" data-studio>
      <span class="tile__text">
        <label class="tile__name" for="monitor-switch" data-name>Studio monitor</label>
        <span class="tile__state" id="monitor-state"><span class="tile__word" data-state>Speakers muted</span></span>
      </span>
      <button class="toggle" id="monitor-switch" type="button" role="switch" aria-checked="false" aria-describedby="monitor-state" data-switch data-autoclic>
        <span class="toggle__drop" aria-hidden="true"></span>
        <canvas class="toggle__art" aria-hidden="true" data-art></canvas>
      </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>

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.

26 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 brass toggle switch” from Animorio and fit it into my site

What it does

On a black background a dark tile with the words Studio monitor and under them, smaller, Speakers muted; next to it is the switch, 56 pixels tall: a plate of oxblood bakelite seen a little from below, with the darker swirls of the resin, a rounded edge that catches the light, a hairline engraved all round, OFF on the left and ON on the right engraved and filled with cream paint, and at each end a domed brass screw with its slot. In the middle, on a washer, a chamfered nickel hex nut holds a threaded bushing, and out of the bushing comes the lever: a rod of polished brass that widens towards the end and finishes in a ball. At rest it leans towards OFF and its soft shadow stretches across the plate to the right. Turned on, the lever starts slowly, as if a finger pushed it against the spring, reaches the dead centre and there it snaps: the spring throws it towards ON, it knocks the stop, bounces a couple of times, less and less, and the plate gives a little jolt. As it turns the reflections of the studio run along the rod and the ball, and the shadow sweeps the plate, longer towards ON. Meanwhile the line under the name slides away and comes back as Speakers live, in brass. With the mouse over the tile the plate turns a little towards the pointer, so the reflections slide across the metal and the bakelite, and over the switch the lever leans a little the other way, as under a finger. The lever can be dragged too: it follows the finger stiffly up to the dead centre and there it gets away and snaps over; let go before that, it falls back on its own.

How it works

A real switch

The plate is a button with role switch and aria-checked, a label for with the name and aria-describedby on the line under it, which changes with the state. Enter and Space turn it on and off, the right arrow turns it on and the left one off, and so does a click on the name; an aria-live line says the new state. The focus ring only shows when the keyboard is in use.

An object made of distances

The shader casts a ray for every pixel and steps along it until it touches something (ray marching): every part is a function that says how far away it is. The plate is an extruded rounded rectangle with a rounded edge, the nut a hexagonal prism cut by two cones, the bushing a tube with a helical thread (its radius changes with the sine of the height plus the angle), the lever a cone with round ends and a ball, turned about its pivot by the lever’s angle. Far from the lever the distance to its box is enough, so the pixels of the plate cost little.

A studio made of light

Round the switch is a studio that only exists as a function of direction: a low softbox on the left (the key light), a strip on the right, a panel above, a pale band low all round and a warm bounce from below. The metals reflect that studio through a Fresnel term, more blurred the rougher they are, and under the horizon of the plate they reflect the bakelite; the bakelite has its own diffuse light and a glossy coat over it. The lever’s shadow is found by marching from the point towards the key light, softened by how close the ray passes to it, and rays that miss the lever’s box are lit straight away.

The engraved letters

OFF, ON and the hairline round the edge are written white on black on a canvas sized in powers of two, a little blurred, and the shader reads them as how deep the groove is: inside is the paint, on the walls the slope bends the normal and darkens the occlusion. The canvas has mipmaps, so the hairline stays whole even with the plate seen at a slant.

The spring over the dead centre

The lever has an angle and a speed worked out four times a frame on gsap.ticker, with the time step held to 1/30 of a second. The spring always pushes it away from the centre, a little at the centre and more towards the stops (SPRING), so it can only rest against one of them; at the stop it bounces keeping BOUNCE of its speed and the plate gives a little jolt with an elastic settle. A click is a finger: a GSAP tween that speeds up to the dead centre (PUSH), then the spring alone. Dragged, the lever follows the finger with some resistance and past the centre it gets away.

Camera and rest

The camera looks at the plate from below (VIEW) and the mouse swings it round the switch about its own up direction, so the plate never tilts sideways; under the mouse the lever leans the other way (PEEK). The shader redraws only when the lever’s angle or the camera changes. Where WebGL is missing the same switch is drawn on a flat canvas with the same camera: gradients, a shadow and a lever that turns.

Values to change

NameFileDefaultWhat it changes
THROWscript.js34How many degrees the lever leans to each side.
SPRINGscript.js260How hard the spring throws the lever over the dead centre: higher, it snaps faster.
BOUNCEscript.js0.42How much of its speed the lever keeps when it knocks its stop (0, it stops dead).
PUSHscript.js0.15The seconds the finger takes to push the lever up to the dead centre.
PEEKscript.js5How many degrees the lever leans the other way under the mouse.
TILTscript.js7How many degrees the plate turns towards the pointer.
VIEWscript.js50How far below the plate it is seen from, in degrees: higher, the lever is seen more in profile.
POLISHscript.js0.16How rough the brass is: 0 a mirror, 0.5 brushed.
LABELSscript.js['OFF', 'ON']The two words engraved in the plate, left and right.
STATESscript.js['Speakers muted', 'Speakers live']The line under the name, off and on.

Try them in the Playground

When to use it

For a switch that needs weight: the monitor or the microphone in a recording or music app, the night mode of a photography site, a setting in a home automation app, an important choice in a product configurator, the control panel of a site with a vintage or industrial feel. The snap and the metal say on even without reading. It is a piece to set on its own, where it is noticed, not in a long list of settings.

On phones

Same size as on a computer: the switch is 184 by 56 pixels and at 390 pixels the name and the plate sit on one line; under 360 pixels the plate shrinks a little, the drawing with it. A tap turns it on and off with the same snap; as soon as the finger rests on it the lever leans a little the other way and the plate turns towards the finger, as with the mouse. The finger can also drag the lever sideways, while up and down the page scrolls.

With reduced motion

No movement: the lever does not turn, the plate does not swing or jolt. Turned on or off, the drawing fades for a moment and comes back with the lever on the other side, and the line under the name changes with a fade. Clicks, taps and keys work as always.

Pitfalls

  • With the camera just below the plate the lever pointed almost at the viewer and showed as a dark stub. Now the plate is seen from 50 degrees below, the pivot sits lower on the plate and the lever is seen in profile, standing tall over the bakelite.
  • With the light from above the lever’s shadow fell towards the viewer, off the plate. The key light is low on the left: the shadow lies across the plate to the right and, as the lever turns, it shortens and lengthens.
  • A flat surface reflects almost the same direction everywhere: a big softbox up there turned the whole bakelite white. The top panel was moved out of that reflection, so only the rounded edges catch it, and the plate when it turns.
  • Swinging the camera about the world’s vertical, with the camera so low, tilted the plate sideways in the picture. Now it swings about its own up direction and never rolls.
  • The hairline engraved round the plate broke into dashes when seen at a slant. The engraving canvas is now 2048 by 1024 with mipmaps, the line is thicker and the slope of the groove is read over four texels.

Libraries

GSAP 3.15.0, Archivo (font variabile) 5.3.0.

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

Testing

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