Groove
motion as tokens
Motion is the last part of a design system nobody tokenised. Groove makes easing, duration and spring first-class tokens, then exports them to every surface a product actually ships on.
The gap
A design system will define eleven greys to three decimal places and then leave every animation in the product to a developer's guess. Color is tokenised. Type is tokenised. Spacing is tokenised. Motion is a number typed inline, in a hurry, in four codebases that do not talk to each other.
The result is a product where the same gesture feels different on web and on iOS, and nobody can say why, because there is no shared object to point at. You cannot review what has no name.
Give it a name
Groove starts by making a motion token a real thing: a name, a curve, a duration, and a note saying what it is for. exit.fast is 150ms on a sharp ease-in, and it is for things leaving that should not compete for attention.
Once motion has names, the rest of a design system's machinery works on it for free. You can diff it. You can review a pull request that changes it. You can ask why enter.settle got 60ms slower and get an answer with a person's name on it.
Three things it does
- AuthorA curve editor with the thing actually moving next to it. Springs are authored by feel — drag mass and damping, watch the settle — then read back as their stiffness values.
- ExportOne token set compiles to CSS custom properties, Motion config, SwiftUI Animation, and Compose AnimationSpec. Spring parameters are converted rather than approximated, so the settle time survives the trip.
- AuditPoint it at a repo and it walks the AST for every hardcoded duration and easing, then tells you which ones are already a token under another name. Most codebases have four durations pretending to be eleven.
The hard part
CSS and SwiftUI do not agree about what a spring is. CSS gives you a cubic bézier and a duration. SwiftUI gives you response and damping fraction. Compose gives you stiffness and damping ratio. Motion gives you all of them and a physics loop.
Converting between them properly means solving the spring rather than eyeballing it — integrating until the amplitude falls under a visibility threshold, then fitting the duration that a bézier would need to cover the same distance in the same felt time. The approximation everyone reaches for first is to match the peak. Matching the settle is what makes it feel the same.
Two surfaces feeling the same is not a coincidence you can hope for. It is a build step.