/* * Motion, as M3's springs. * * M3 Expressive moves on physics, not on a duration and a curve: every transition is a * spring with a damping ratio and a stiffness. CSS cannot run a spring, so each one is * sampled into a `linear()` easing — 49 points, past the resolution anyone can see at 60 Hz — * by bin/springs.mjs (`npm run build:springs`), which carries the maths and the derivation. * The constants are androidx Compose Material 3's own ({Expressive,Standard}MotionTokens.kt, * Apache-2.0, © Google LLC, androidx-main @ 1608250): * * spatial — position, size, shape. Underdamped, so the Expressive fast one overshoots by 9% * and settles back: that small bounce is what reads as Expressive. * effects — colour and opacity. Critically damped; a colour must never overshoot. * * Each spring is sampled over the duration M3 publishes for the web * (docs/reference/m3/styles.md § Motion, "Web curve equivalents"), so the `*-duration` tokens * read Google's numbers: spatial 350/500/650 ms, effects 150/200/300 ms. Sampling is in real * time — point i is the spring's value at `duration × i / 48` — so the bounce lands at the same * millisecond whatever the duration is. Where the duration outlasts the spring the tail is flat * at 1; where it is shorter the final point is pinned to 1, which closes at most 0.3% of the * travel in the last frame. Each token's comment records damping, stiffness, the settle time * (when the spring stays within 0.1% of its travel) and the duration it was sampled over. * * Use a pair together, easing and duration, or the curve is stretched over the wrong time * and the bounce lands late: * * transition: transform var(--md-sys-motion-spatial-fast-duration) var(--md-sys-motion-spatial-fast); * class="transition-transform duration-(--md-sys-motion-spatial-fast-duration) ease-spatial-fast" * * M3 has two motion schemes. Expressive is the default here and the values above; Standard * ("minimal bounce, for utilitarian products") swaps the three spatial springs when the theme * script writes `data-motion="standard"` on . Its effects springs are the same ones, so * only spatial is overridden. A component never names a scheme: it names a spring. * * The cubic-bezier easings below are M3's non-spring set (@material/web token values, * Apache-2.0, © Google LLC), for the few places a duration is fixed by something outside * the page — a view transition, an animated scroll. * * Reduced motion zeroes every duration here, both schemes, so anything that animates through * these tokens turns instant with no per-component check; anything that animates without them * is a bug. */ :root { /* damping 0.6, stiffness 800; settles in 360ms; peaks at 1.095 at 139ms; sampled over 350ms */ --md-sys-motion-spatial-fast: linear(0, 0.0195, 0.0716, 0.1471, 0.2381, 0.3378, 0.4404, 0.5416, 0.6378, 0.7265, 0.806, 0.8754, 0.9342, 0.9826, 1.0211, 1.0503, 1.0713, 1.0849, 1.0924, 1.0948, 1.0931, 1.0882, 1.0812, 1.0726, 1.0632, 1.0534, 1.0438, 1.0347, 1.0263, 1.0187, 1.0121, 1.0064, 1.0018, 0.9981, 0.9953, 0.9933, 0.992, 0.9913, 0.991, 0.9912, 0.9916, 0.9923, 0.9931, 0.994, 0.9949, 0.9958, 0.9967, 0.9975, 1); --md-sys-motion-spatial-fast-duration: 350ms; /* damping 0.8, stiffness 380; settles in 440ms; peaks at 1.015 at 269ms; sampled over 500ms */ --md-sys-motion-spatial-default: linear(0, 0.0185, 0.0663, 0.1336, 0.2126, 0.2973, 0.3832, 0.4669, 0.5461, 0.6192, 0.6854, 0.7443, 0.7958, 0.8402, 0.8779, 0.9094, 0.9354, 0.9564, 0.9731, 0.9861, 0.996, 1.0033, 1.0085, 1.0119, 1.014, 1.015, 1.0152, 1.0148, 1.014, 1.0129, 1.0117, 1.0104, 1.0091, 1.0078, 1.0066, 1.0055, 1.0046, 1.0037, 1.0029, 1.0023, 1.0017, 1.0013, 1.0009, 1.0006, 1.0004, 1.0002, 1, 0.9999, 1); --md-sys-motion-spatial-default-duration: 500ms; /* damping 0.8, stiffness 200; settles in 600ms; peaks at 1.015 at 370ms; sampled over 650ms */ --md-sys-motion-spatial-slow: linear(0, 0.0166, 0.0597, 0.1211, 0.1939, 0.273, 0.354, 0.434, 0.5107, 0.5826, 0.6487, 0.7084, 0.7615, 0.8081, 0.8484, 0.8829, 0.912, 0.9361, 0.9559, 0.9719, 0.9845, 0.9943, 1.0017, 1.0071, 1.0108, 1.0132, 1.0146, 1.0151, 1.0151, 1.0145, 1.0137, 1.0126, 1.0114, 1.0102, 1.009, 1.0078, 1.0067, 1.0057, 1.0047, 1.0039, 1.0031, 1.0025, 1.0019, 1.0015, 1.0011, 1.0008, 1.0005, 1.0003, 1); --md-sys-motion-spatial-slow-duration: 650ms; /* damping 1.0, stiffness 3800; settles in 150ms; sampled over 150ms */ --md-sys-motion-effects-fast: linear(0, 0.0163, 0.0576, 0.1147, 0.1807, 0.2507, 0.3214, 0.3902, 0.4558, 0.5172, 0.5737, 0.6253, 0.6718, 0.7136, 0.7508, 0.7837, 0.8128, 0.8383, 0.8606, 0.8801, 0.897, 0.9117, 0.9244, 0.9353, 0.9448, 0.9529, 0.9599, 0.9658, 0.9709, 0.9753, 0.979, 0.9822, 0.9849, 0.9872, 0.9892, 0.9909, 0.9923, 0.9935, 0.9945, 0.9954, 0.9961, 0.9967, 0.9972, 0.9977, 0.998, 0.9983, 0.9986, 0.9988, 1); --md-sys-motion-effects-fast-duration: 150ms; /* damping 1.0, stiffness 1600; settles in 240ms; sampled over 200ms */ --md-sys-motion-effects-default: linear(0, 0.0124, 0.0446, 0.0902, 0.1443, 0.2032, 0.2642, 0.3253, 0.3849, 0.4422, 0.4963, 0.547, 0.594, 0.6372, 0.6768, 0.7127, 0.7452, 0.7745, 0.8009, 0.8244, 0.8454, 0.8641, 0.8807, 0.8954, 0.9084, 0.9199, 0.93, 0.9389, 0.9467, 0.9536, 0.9596, 0.9648, 0.9694, 0.9734, 0.9769, 0.98, 0.9826, 0.985, 0.987, 0.9887, 0.9902, 0.9916, 0.9927, 0.9937, 0.9946, 0.9953, 0.9959, 0.9965, 1); --md-sys-motion-effects-default-duration: 200ms; /* damping 1.0, stiffness 800; settles in 330ms; sampled over 300ms */ --md-sys-motion-effects-slow: linear(0, 0.0139, 0.0496, 0.0995, 0.1583, 0.2216, 0.2865, 0.3509, 0.4131, 0.4722, 0.5275, 0.5788, 0.6258, 0.6687, 0.7075, 0.7424, 0.7737, 0.8016, 0.8264, 0.8484, 0.8678, 0.8849, 0.8999, 0.9131, 0.9247, 0.9347, 0.9435, 0.9512, 0.9578, 0.9636, 0.9686, 0.973, 0.9767, 0.98, 0.9828, 0.9852, 0.9873, 0.9891, 0.9907, 0.992, 0.9931, 0.9941, 0.995, 0.9957, 0.9963, 0.9969, 0.9973, 0.9977, 1); --md-sys-motion-effects-slow-duration: 300ms; --md-sys-motion-easing-standard: cubic-bezier(0.2, 0, 0, 1); --md-sys-motion-easing-standard-accelerate: cubic-bezier(0.3, 0, 1, 1); --md-sys-motion-easing-standard-decelerate: cubic-bezier(0, 0, 0, 1); --md-sys-motion-easing-emphasized: cubic-bezier(0.2, 0, 0, 1); --md-sys-motion-easing-emphasized-accelerate: cubic-bezier(0.3, 0, 0.8, 0.15); --md-sys-motion-easing-emphasized-decelerate: cubic-bezier(0.05, 0.7, 0.1, 1); --md-sys-motion-duration-short: 150ms; --md-sys-motion-duration-medium: 300ms; --md-sys-motion-duration-long: 500ms; } /* * The Standard scheme: the same three spatial springs at a damping ratio of 0.9, which leaves * a 0.2% overshoot instead of Expressive's 9% — motion that eases into place rather than * bouncing. Google's web durations for them are 350/500/750 ms; the effects springs, the * legacy easings and every other token are the ones above. */ [data-motion="standard"] { /* damping 0.9, stiffness 1400; settles in 230ms; peaks at 1.002 at 193ms; sampled over 350ms */ --md-sys-motion-spatial-fast: linear(0, 0.0316, 0.1076, 0.2062, 0.313, 0.4185, 0.517, 0.6056, 0.6828, 0.7486, 0.8036, 0.8487, 0.8852, 0.9142, 0.937, 0.9546, 0.968, 0.9781, 0.9856, 0.991, 0.9948, 0.9975, 0.9992, 1.0004, 1.001, 1.0014, 1.0015, 1.0015, 1.0014, 1.0013, 1.0011, 1.001, 1.0008, 1.0007, 1.0005, 1.0004, 1.0003, 1.0003, 1.0002, 1.0001, 1.0001, 1.0001, 1.0001, 1, 1, 1, 1, 1, 1); --md-sys-motion-spatial-fast-duration: 350ms; /* damping 0.9, stiffness 700; settles in 320ms; peaks at 1.002 at 272ms; sampled over 500ms */ --md-sys-motion-spatial-default: linear(0, 0.0322, 0.1094, 0.2094, 0.3173, 0.4237, 0.5227, 0.6114, 0.6886, 0.7541, 0.8086, 0.8532, 0.8891, 0.9175, 0.9397, 0.9569, 0.9699, 0.9796, 0.9867, 0.9918, 0.9954, 0.9979, 0.9995, 1.0006, 1.0011, 1.0014, 1.0015, 1.0015, 1.0014, 1.0012, 1.0011, 1.0009, 1.0007, 1.0006, 1.0005, 1.0004, 1.0003, 1.0002, 1.0002, 1.0001, 1.0001, 1.0001, 1, 1, 1, 1, 1, 1, 1); --md-sys-motion-spatial-default-duration: 500ms; /* damping 0.9, stiffness 300; settles in 490ms; peaks at 1.002 at 416ms; sampled over 750ms */ --md-sys-motion-spatial-slow: linear(0, 0.0311, 0.1061, 0.2037, 0.3095, 0.4143, 0.5125, 0.6009, 0.6782, 0.7442, 0.7995, 0.8451, 0.882, 0.9115, 0.9347, 0.9527, 0.9665, 0.9769, 0.9846, 0.9903, 0.9943, 0.9971, 0.999, 1.0002, 1.0009, 1.0013, 1.0015, 1.0015, 1.0014, 1.0013, 1.0012, 1.001, 1.0008, 1.0007, 1.0006, 1.0005, 1.0004, 1.0003, 1.0002, 1.0002, 1.0001, 1.0001, 1.0001, 1, 1, 1, 1, 1, 1); --md-sys-motion-spatial-slow-duration: 750ms; } @media (prefers-reduced-motion: reduce) { :root, [data-motion="standard"] { --md-sys-motion-spatial-fast-duration: 0ms; --md-sys-motion-spatial-default-duration: 0ms; --md-sys-motion-spatial-slow-duration: 0ms; --md-sys-motion-effects-fast-duration: 0ms; --md-sys-motion-effects-default-duration: 0ms; --md-sys-motion-effects-slow-duration: 0ms; --md-sys-motion-duration-short: 0ms; --md-sys-motion-duration-medium: 0ms; --md-sys-motion-duration-long: 0ms; } }