A government benefits application ships on the web and two native platforms, and its motion feels inconsistent across them. How do you define duration and easing tokens that hold across all three?
answer
- hard-coded values per platform
- one scale, one set of roles
- format types for time and curves
- leave native navigation motion native
- same intent, platform-appropriate feel
basics
~20 sReplace per-platform hard-coded values with one shared duration scale and easing-role set, stored as tool-agnostic tokens and converted per platform. Keep each platform's own navigation motion, and aim for the same intent rather than identical numbers.
solid answer
~40 sThe inconsistency usually comes from each platform team hard-coding its own numbers and default curves. I would define one **motion vocabulary**: a short duration scale (short, medium, long), the easing roles (standard, decelerate, accelerate) and, if needed, a critically damped spring for gestures. I store it in a tool-agnostic format — the Design Tokens Community Group draft offers `duration` tokens whose value is an object with a number and a unit, `cubicBezier` tokens, and a `transition` composite that references them — and a pipeline emits each platform's representation. Components reference motion by purpose, such as “expand section”, not by number. I **leave platform-native navigation and system transitions alone**, because users expect them. Then I verify with side-by-side recordings. The goal is the same intent everywhere, not identical milliseconds.
code
json · 22 lines{
"motion": {
"duration": {
"short": { "$type": "duration", "$value": { "value": 100, "unit": "ms" } },
"medium": { "$type": "duration", "$value": { "value": 250, "unit": "ms" } },
"long": { "$type": "duration", "$value": { "value": 400, "unit": "ms" } }
},
"easing": {
"standard": { "$type": "cubicBezier", "$value": [0.4, 0, 0.2, 1] },
"decelerate": { "$type": "cubicBezier", "$value": [0, 0, 0.5, 1] },
"accelerate": { "$type": "cubicBezier", "$value": [0.5, 0, 1, 1] }
},
"expand-section": {
"$type": "transition",
"$value": {
"duration": "{motion.duration.medium}",
"delay": { "value": 0, "unit": "ms" },
"timingFunction": "{motion.easing.standard}"
}
}
}
}go deeper
Recall that motion values should come from shared duration and easing tokens, not numbers typed into each component on each platform.
Explain the draft format's duration, cubicBezier and transition types, why springs need grouped number tokens, and how purpose tokens reference the scale.
Show how you would inventory inconsistent motion across three platforms, define one vocabulary, leave native navigation alone and verify with side-by-side recordings.
Discuss the trade-off between cross-platform consistency and platform-native feel, and who arbitrates when a platform team wants to diverge from the shared vocabulary.
## Diagnose where the inconsistency comes from Motion that feels different across platforms rarely has one cause. The usual suspects: - **Hard-coded values.** Each team typed its own durations: 200 milliseconds on the web, 350 on one native app, the platform default on the other. - **Different default curves.** Each platform's animation system has its own default easing, and teams that never chose one inherited three different feels. - **Mixed families.** One platform uses springs for everything, another uses curves, so the same interaction feels bouncy in one place and crisp in another. - **Overridden system motion.** A team replaced its platform's standard navigation transition with a custom one to match the web, and now the app feels foreign on that platform. An inventory — recording the same flows on all three platforms side by side — shows which of these apply. ## Define one motion vocabulary A shared vocabulary is small: 1. **Duration scale** — short, medium, long (and perhaps extra long), with values chosen as common practice and tested at full speed. 2. **Easing roles** — standard for moves within the screen, decelerate for entering, accelerate for leaving, plus emphasized variants if the product needs them. 3. **Springs, if used** — a small set of named springs, usually critically damped, for gesture-driven motion. 4. **Purpose tokens** — motion for specific jobs, such as “expand section” or “panel enter”, that reference the scale and roles. Components use these, never raw values. ## Store it in a tool-agnostic format The Design Tokens Community Group format draft covers most of this: | Need | Draft type | Value shape | |---|---|---| | A duration | `duration` | An object with a numeric `value` and a `unit` of “ms” or “s” | | An easing curve | `cubicBezier` | Four numbers: two control points, x values between 0 and 1 | | A complete transition | `transition` | A composite of duration, delay and timing function, each a value or a reference | | A spring | none | Model as a group of number tokens, such as damping ratio and response | References use curly braces, so a purpose token points at `{motion.duration.medium}` rather than repeating a number. The draft's `$extensions` field is meant for optional metadata, not for values the token cannot be understood without, which is why spring parameters belong in ordinary number tokens instead. ## Generate each platform's output A token pipeline converts the shared source into what each platform consumes: milliseconds or seconds as that platform expects, curve objects, and spring objects assembled from the grouped numbers. Where a platform cannot express something natively — for example a spring on a surface that only accepts curves — the pipeline documents the approximation it uses, so nobody is surprised by a difference. ## Respect platform differences on purpose Consistency does not mean identical numbers everywhere: - **Native navigation and system transitions stay native.** Pushing a new screen, presenting a sheet, going back — users know how these feel on their platform, and replacing them makes the app feel foreign. Tokens govern the product's own custom motion. - **Screen size.** Many systems use slightly longer durations on large screens, where elements travel further, as a documented adjustment per size class. - **User settings.** Platforms let users reduce motion or change animation speed system-wide; the token layer is the natural place to apply those preferences centrally. What a reduced alternative looks like is a separate accessibility decision. The standard for success is **the same intent**: a section expanding feels equally quick and calm on every platform, even if one platform's value is a few milliseconds different. ## Verify and keep it true - Record the same flows on every platform and compare them frame by frame after each release. - Add a lint rule or review check that flags raw duration numbers and curve values in component code. - Document each purpose token with a short clip, so designers and engineers share one reference for what “panel enter” should look like. ## Pitfalls during the rollout - **Migrating numbers instead of intent.** Mapping every old value to its nearest scale step keeps inconsistent choices; map each animation to its purpose first, then to a step. - **Too many steps.** A scale of twelve durations recreates per-component values under new names; three or four steps cover most interfaces. - **Forgetting delay.** Hard-coded delays drift just like durations; the transition composite's delay should reference the scale too.
- Should the web app copy a native platform's navigation transition so all three match?Usually not. Native navigation motion is part of how each platform feels, and web users have their own expectations. Aligning the product's custom motion through shared tokens gives consistency where it matters; forcing one platform's system transitions onto the others makes at least one of them feel foreign.
- How do you stop teams from reintroducing hard-coded motion values?Make the tokens the easiest path: components expose motion through purpose tokens, and a lint rule or review check flags raw durations and curve numbers in component code. Pair it with a documented clip per purpose token, so a team asking for a new motion starts from the vocabulary instead of a number.
- Why not store spring parameters in each token's extensions field?The Design Tokens Community Group draft says extension data should be restricted to optional metadata that is not crucial to understanding the token's value. A spring's damping and response are the value itself, so they belong in ordinary number tokens grouped per spring, which every platform's pipeline can read.
saying these in an interview costs you the question
- Consistency means every platform uses identical millisecond values.
- Override each platform's navigation transitions to match the web.
- A duration token's value is one free-text string holding number and unit.
- Each platform team should tune its own motion values independently.
- Components may embed raw curve numbers as long as they match the tokens.