Motion tokens
Skill almasumdev/awesome-mobile-design-system-agent-skills/.github/skills/motion/motion-tokens
Encoding duration, easing, and stagger as DTCG tokens and delivering them to Compose, SwiftUI, Flutter, and React Native. Use this when introducing or refactoring motion tokens.From its SKILL.md
npx -y skills add almasumdev/awesome-mobile-design-system-agent-skills --skill motion-tokensAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
5.6 KB, ~1.6k tokens by cl100k_base, as published. Nobody here has run it
Motion Tokens
Instructions
Motion belongs in the token system. A component should no more embed 250ms than it should embed #4F46E5.
1. DTCG Types for Motion
DTCG ships duration and cubicBezier. Compose motion via transition groups.
{
"motion": {
"duration": {
"$type": "duration",
"xs": { "$value": "80ms" },
"sm": { "$value": "150ms" },
"md": { "$value": "250ms" },
"lg": { "$value": "400ms" }
},
"easing": {
"$type": "cubicBezier",
"standard": { "$value": [0.2, 0.0, 0.0, 1.0] },
"accelerate": { "$value": [0.3, 0.0, 1.0, 1.0] },
"decelerate": { "$value": [0.0, 0.0, 0.0, 1.0] },
"emphasized": { "$value": [0.2, 0.0, 0.0, 1.0] }
}
}
}
2. Semantic Motion Aliases
Components consume intent-bearing aliases, not raw motion.duration.md.
{
"motion": {
"transition": {
"stateChange": {
"$type": "transition",
"$value": {
"duration": "{motion.duration.sm}",
"timingFunction": "{motion.easing.standard}",
"delay": "0ms"
}
},
"surfaceEnter": {
"$type": "transition",
"$value": {
"duration": "{motion.duration.md}",
"timingFunction": "{motion.easing.decelerate}",
"delay": "0ms"
}
},
"surfaceExit": {
"$type": "transition",
"$value": {
"duration": "{motion.duration.sm}",
"timingFunction": "{motion.easing.accelerate}",
"delay": "0ms"
}
},
"stagger": {
"$type": "duration",
"$value": "30ms"
}
}
}
}
3. Style Dictionary Transforms
Style Dictionary does not ship duration / cubicBezier transforms out of the box for native platforms. Add small custom transforms.
// style-dictionary.config.js
const StyleDictionary = require('style-dictionary');
StyleDictionary.registerTransform({
name: 'duration/ms-to-number',
type: 'value',
matcher: t => t.$type === 'duration',
transformer: t => parseInt(String(t.$value).replace('ms', ''), 10),
});
StyleDictionary.registerTransform({
name: 'cubicBezier/array',
type: 'value',
matcher: t => t.$type === 'cubicBezier',
transformer: t => t.$value, // [x1,y1,x2,y2]
});
StyleDictionary.registerTransformGroup({
name: 'compose-motion',
transforms: ['attribute/cti', 'name/cti/pascal', 'duration/ms-to-number', 'cubicBezier/array'],
});
4. Compose Delivery
object Motion {
object Duration {
const val Xs = 80
const val Sm = 150
const val Md = 250
const val Lg = 400
}
val EasingStandard = CubicBezierEasing(0.2f, 0.0f, 0.0f, 1.0f)
val EasingDecelerate = CubicBezierEasing(0.0f, 0.0f, 0.0f, 1.0f)
val EasingAccelerate = CubicBezierEasing(0.3f, 0.0f, 1.0f, 1.0f)
}
val SurfaceEnter = tween<Float>(Motion.Duration.Md, easing = Motion.EasingDecelerate)
5. SwiftUI Delivery
public enum DSMotionDuration { public static let xs = 0.08, sm = 0.15, md = 0.25, lg = 0.4 }
public enum DSMotionEasing {
public static let standard = Animation.timingCurve(0.2, 0.0, 0.0, 1.0, duration: DSMotionDuration.md)
public static let decelerate = Animation.timingCurve(0.0, 0.0, 0.0, 1.0, duration: DSMotionDuration.md)
public static let accelerate = Animation.timingCurve(0.3, 0.0, 1.0, 1.0, duration: DSMotionDuration.sm)
}
6. Flutter Delivery
class AppMotion extends ThemeExtension<AppMotion> {
final Duration surfaceEnter;
final Duration surfaceExit;
final Curve standard;
final Curve decelerate;
const AppMotion({
required this.surfaceEnter, required this.surfaceExit,
required this.standard, required this.decelerate,
});
static const standard = AppMotion(
surfaceEnter: Duration(milliseconds: 250),
surfaceExit: Duration(milliseconds: 150),
standard: Cubic(0.2, 0.0, 0.0, 1.0),
decelerate: Cubic(0.0, 0.0, 0.0, 1.0),
);
@override AppMotion copyWith(...) => ...;
@override AppMotion lerp(ThemeExtension<AppMotion>? other, double t) => this;
}
7. React Native Delivery
export const motion = {
duration: { xs: 80, sm: 150, md: 250, lg: 400 },
easing: {
standard: Easing.bezier(0.2, 0.0, 0.0, 1.0),
decelerate: Easing.bezier(0.0, 0.0, 0.0, 1.0),
accelerate: Easing.bezier(0.3, 0.0, 1.0, 1.0),
},
} as const;
8. Reduced-Motion Variant
Ship a second token file motion.reduced.json where every duration resolves to 0ms. The platform provider picks the right file at runtime based on the accessibility flag.
9. Anti-Patterns
tween(300)inline in a component.- Using CSS-string easings on native platforms instead of cubic-bezier arrays.
- Exposing reference durations (
motion.duration.md) as the component-facing API. - Hardcoding stagger in component source — tokenize it.
Checklist
- Duration and easing are DTCG
duration/cubicBeziertokens with semantictransitionaliases. - Style Dictionary has explicit transforms for duration and cubic-bezier output per platform.
- Every target platform has a generated motion artifact (Compose
Motion, SwiftUIDSMotion…, FlutterThemeExtension, RN const). - Components consume semantic motion tokens (
transition.stateChange) only. - A reduced-motion token file is delivered and selected at runtime.
- No raw millisecond or cubic-bezier literals exist in component source.
What ships with it
Read from the repository
Just SKILL.md. No reference files, no scripts.