Skip to content
Spring physics on a microcontroller: how kadokit animates

Spring physics on a microcontroller: how kadokit animates

July 5, 2026

In June 2026 we published a set of ten demos running on a low-cost ESP32-S3: smooth spring-animated interfaces using only a few tens of kilobytes of SRAM, built with what has since become kadokit (shown there under an earlier working name). To our knowledge, that was the first time spring-physics UI animation had run on microcontroller-class embedded hardware at all — and it carried a second first: the springs were declared, as a property in a UI description, not written by hand as physics code.

This post explains what that means and why it matters for embedded products.

The motion standard that phones set

Spring physics were first formally introduced to mainstream UI in iOS 7 (released September 2013). Apple transformed mobile interactions by using spring-based timing curves to create fluid, natural, and interruptible interface animations. In the decade since, spring motion became the default vocabulary of interaction design on iOS, on Android, and on the web.

Embedded screens never got that upgrade: interfaces on microcontrollers shipped with fixed easing curves at best and hard cuts at worst, while the people using those devices spend all day with phones. Our June 2026 demos were, to our knowledge, the first to close that gap.

How it’s closed matters as much as the fact. Recreating spring motion by hand means a custom frame timer, damping equations, velocity tracking, and a per-component state machine in C — expert work, redone for every component. In kadokit, spring motion is a built-in property of the UI description.

Why springs, not just easings

Every animation system has easing curves; kadokit has 26 of them. But easing-based motion has a fundamental limitation: it’s a fixed clip. If the target changes mid-flight: the user taps again, a sensor updates, a card is flung. A tweened animation either snaps, restarts, or stacks.

A spring is different: it’s a physical model, not a clip. It has a current position and a velocity, so when the target changes mid-motion, the animation continues naturally from where it is, at the speed it was already moving. That interruptibility is exactly what made iOS 7 feel alive, and kadokit treats it as a first-class citizen next to tweens:

arc { value bind="app.speed" spring="snappy" }

Six presets (snappy, gentle, soft, sheet, overshoot, critically-damped) cover most needs; spring-duration and spring-bounce give full control when they don’t.

Beyond single-property animation

The demos aren’t just sliders with bounce. The same declarative approach covers the full vocabulary of contemporary interface motion:

  • Staggered motion groups: one declaration animates a whole grid of widgets in a timed wave, replayable from a tap or a timer.
  • Velocity-aware gestures: a flick and a slow drag are distinguished naturally, and a released card carries its momentum into the spring that settles it.
  • Layout animations: when a list is shuffled or sorted, items glide from their old position to their new one automatically.
  • Animation as a property annotation: motion is configured where the property is bound. Every change, whether from touch, state, or a sensor, moves through the same configuration. There is no separate animation code to write or keep in sync.

Fast enough for a microcontroller

Spring physics has a reputation as phone-class math, too heavy for a small chip. The kadokit motion engine was designed for constrained hardware from day one: the expensive work is prepared ahead of time so that very little remains to compute per frame, animations run within a fixed memory budget set when the product is built, and all updates are applied in a single pass per display refresh.

The result is what the demos show: ten interfaces on an ESP32-S3, tens of kilobytes of SRAM, smooth motion throughout.

Predictable enough to ship

Embedded products have a different bar than websites: an animation glitch in a vehicle dashboard is a defect report. The behavior that matters:

  • What you approve is what ships. The interface is designed and reviewed on desktop, and the device runs the same compiled document. The motion you validated is the motion in the field.
  • Nothing improvises at runtime. Animations are declared in the UI document, not programmed: no custom code runs during an animation, and nothing can be injected into the motion path after the product ships.
  • Values always arrive. However busy the system gets, a bound property always lands at its target state. Motion degrades gracefully, never into a stuck or half-finished interface.

Try it with your UI

The original demo offer still stands: if you’re curious how an interface built with another tool would behave rewritten in kadokit, write to embedded@aptum.fr and we’ll convert it for you.

For the full animation vocabulary: tweens, springs, motion groups, see the Animations documentation.