Motion Inspector
A Chrome extension that pauses and scrubs the animations on any page and exports each one as CSS, a linear() easing, Motion or GSAP, built in vanilla TypeScript on WXT.
Browser Extension Development & Tooling
2 Days

Introduction
A Chrome extension that pauses and scrubs the animations on any page and exports each one as CSS, a linear() easing, Motion or GSAP, built in vanilla TypeScript on WXT.
Work Done
Chrome Extension

Challenges
Catching transitions that finish in a few hundred milliseconds, reading GSAP from outside the page, and turning a spring the browser only sees as a sampled linear() curve back into code a developer would write.

Solutions
A page agent injected into the MAIN world on demand that wraps Element.prototype.animate and listens for transitionrun, holding finished animations so they can still be exported. A spring fit that searches damping and frequency and writes type: "spring" when the error is under 1.5%.


Results
Released as v0.3.0 on GitHub: four export formats, a waveform transport with frame stepping and J/K/L keys, 99 passing unit tests and a Playwright run against the built extension. The CSS export still drops a GSAP repeatDelay.
Details
The gap
Chrome DevTools can pause and scrub a page's animations, but it never hands you code. I wanted to freeze an animation on any site and copy it out as CSS, a `linear()` easing, Motion or GSAP. Motion Inspector does that from Chrome's side panel, which stays open while you hover and scroll the page.
One call per command
There is no message bridge. Every command from the panel is a single `chrome.scripting.executeScript` into the page's MAIN world, the only place that can see `window.gsap` and wrap `Element.prototype.animate`. That wrapper, plus capture-phase `transitionrun` listeners, is how a 200 ms hover transition gets caught before `getAnimations()` forgets it.
Springs come back as springs
Motion hands a spring to the browser as a `linear()` curve with dozens of sampled stops. Pasting that back helps nobody, so the exporter grid-searches damping and frequency against the curve. When the fit lands under 1.5% RMS error, the Motion tab writes `type: "spring"` with `bounce` and `visualDuration` instead.
A waveform for a timeline
The scrubber's bars show how many animations run at each moment, laid out in whole device pixels from a ResizeObserver. A Playwright run checks the panel never scrolls sideways at widths from 300 to 600px. The CSS export still drops a GSAP `repeatDelay`, and that is the next fix.
Tope Akintola
November 2, 2026
Browser Extension Development & Tooling
