Standard
A simple ease for symmetrical motion that can be used as a default.
Motion is often the least developed part of a design system. This exploration makes it foundational, starting with well-curated primitives and building up to fully realized choreography.
Motion is often complex. Choreographing multiple objects and properties to work together across a timeline takes thoughtful consideration. Perhaps it is the nature of that complexity, combined with a token format that can't describe sequences, that causes most design systems to ship with minimal consideration for motion.
Even mature systems only include motion in the form of key/value pairs. Sometimes they include notes or documentation for guidance on how to use those motion tokens. But often it is left to the engineers to ultimately choose the right tokens and piece together a motion experience.
What if we could change that narrative and work towards a system that characterizes motion beyond simple key/value pairs? A system that aims to standardize more complex, choreographed sequences involving multiple phases or elements. One that is easily understood by both humans and agents. Those are the goals of this motion design system.
The goal of the primitives tier is to curate values and establish vocabulary. It's important to choose values that support both functional and expressive motion. But it is just as important to establish a vocabulary that both humans and agents can understand.
Durations should be structured as a descriptive ladder that speaks to intent, giving humans and agents a shared vocabulary. The rungs let consumers reach for the pace that best fits the motion, whether functional or expressive.
| Name | Value | Example |
|---|---|---|
| Quick & Short For functional interactions where we want the UI to feel fast and responsive. | ||
|
|
||
| Medium, Long & Extra-Long For functional motion that demands a little more time, whether through positional travel or choreography. | ||
|
|
||
| Super-Long & Cinematic For storytelling motion that is meant to be less functional and more attention grabbing. | ||
|
|
||
Create curves that support both function and expression, while establishing a vocabulary that speaks to intent.
A simple ease for symmetrical motion that can be used as a default.
Function focused curves with clear, descriptive naming that describes the motion's intent.
More expressive curves, used less for function and more for storytelling.
Used for continuous motion, such as loaders.
The goal of the semantic tier is defining which primitives to use, and when to use them. It allows us to standardize common interactions and build upon our foundational vocabulary. Since this is the layer most of the UI reaches for, it is important to choose names that speak to the usage intent so both humans and agents understand the motion's purpose.
Each token is a simple recipe that pairs duration with easing and provides a name that describes where it's used.
--motion-use-hoverquick standardHover is the most common interaction for desktop users. We want it to feel fast and responsive so we pair a quick duration with a standard easing.
--motion-use-focusquick entranceFocus needs the same speed as hover but a different intent. Swapping in an entrance curve lets the ring settle into place, anchoring the eye as someone tabs through a page.
--motion-use-disclosure-inshort entrance--motion-use-disclosure-outquick exitSome interactions benefit from two corresponding tokens. One for entrance, that gives content time to settle. And one for exit, to get content out of the way quickly.
The goal of the choreography tier is to express more complex motion that standard
key/value tokens can not do alone. Coordinated motion between multiple elements, or a
single element with multiple phases, can be captured as a JSON token that follows the DTCG
structure, extended with a custom choreography type the standard doesn't
yet define. Each choreography token references the previous tiers and follows the same
principles of named intent.
Height eases open and closed on the accordion choreography, never a jump cut.
The spec shown here is the compiled runtime output. For an example of a raw token, see the Intent section below.
The choreography tokens are intended to be the missing motion blueprint. The token format is platform agnostic and the concept can be adapted to fit any codebase. For web based projects, such as this one, a small runtime built on the Web Animations API reads the tokens and plays them back.
A core concept of this entire project is to make motion a foundational principle, not
an after thought. And reduced motion is no different. The systems structure supports
reduced motion throughout, including a reducedMotion collapse for each
choreography token. Reduced motion doesn't mean "no motion". The motion should be able
to adapt for users that prefer less movement.
Same trigger, two behaviors. With full motion the rows rise into place one after another. Switch to reduced and reveal again, and the same token collapses to a single fade with no travel.
Another important goal of this motion system is intent. As noted in each tier, we want to establish a consistent, shared vocabulary. We choose token names that speak to the motion's usage and purpose. In doing so, we create a motion system that describes itself.
This approach is helpful for humans using the system. But it is even more important for the AI agents we now incorporate into our workflows. Humans can visualize motion, but agents can not.
Establishing vocabulary and named intent provides agents with the blueprint they need to
understand the system. For humans interacting with agents, this also gives us the shared
language we need to describe the motion we want to build. But we can take things a step
further and double down on context for agents (and humans) by shipping ai.intent
in our tokens.
"quick": {
"$type": "duration",
"$value": { "value": 100, "unit": "ms" },
"$extensions": {
"ai.intent": {
"usage": ["hover", "focus", "press", "toggles"],
"direction": "The fastest perceptible response — snappy for dense UI; reads near-instant.",
"constraints": { "range": { "min": 80, "max": 140, "unit": "ms" } }
}
}
}
quick duration primitive (Tier 1), straight from the token source. Its
intent bounds a range a linter can check.
"choreography-modal-enter": {
"$type": "choreography",
"$value": {
"pattern": "coordinated",
"target": ".modal-root",
"tracks": [
{ "selector": ".modal-root", "keyframes": "fade-in", "motion": "medium entrance", "delay": "0ms" },
{ "selector": ".modal-card", "keyframes": "pop", "motion": "long emphasized", "delay": "quick" }
],
"reducedMotion": {
"collapseTo": "coordinated",
"tracks": [
{ "selector": ".modal-card", "keyframes": "fade-in", "motion": "fade entrance", "delay": "0ms" }
]
}
},
"$extensions": {
"ai.intent": {
"usage": ["dialogs", "confirmations", "focal overlays"],
"direction": "The backdrop (.modal-root) fades while the card (.modal-card) pops. The card is the focal point, so it gets the emphasized curve and a `quick` delay behind the backdrop."
}
}
}
modal-enter choreography (Tier 3), straight from the token source. Its
intent names where it belongs, and it carries its own reduced-motion collapse.
The ai.intent provides more than usage context for the agents. It also
provides constraints. This helps produce more consistent output, while also increasing
automation capabilities. Evals and linters can be run against the motion system to check
for drift, helping us ensure consistent use of motion throughout a codebase.
Too often motion is considered as an after thought. It's the polish that teams look to add in the final stages, if time allows. But motion is essential to great user experiences. Motion is more than fancy animations or storytelling. It provides responsive feedback, communicates changes, helps anchor users, and so much more.
I believe motion should be as foundational in our design systems as colors, spacing, and typography. The vision of capturing motion within a system is a challenge, but it is one I think is worth exploring. That is part of the reason why I created this platform and this system.
If you've made it this far, then everything you just read through is a summarized version of my work over the past six months. The snippets sampled here are part of a larger, fully functioning motion design system that has been refined and deployed in multiple production environments. The knowledge I've gained along the way has only fueled my desire to continue working with motion, and I hope you've found value in it as well.
The task of tokenizing complex motion is an ongoing one. My goal with this platform is to continue exploring and sharing ways of working with motion, both within a design system, and for modern agentic workflows. I plan to share articles, token generators, and the full motion design system on motiondesignsystem.org very soon. But for now, I hope the ideas shared in this overview help provide insight on how we can better work with motion.
If you're doing any work with motion in design systems, I would love to hear from you!
info@motiondesignsystem.org