Scale Duration With Travel Distance
SHOULD: Derive duration from travel distance, sublinearly — 100px = base, 200px = 1.3x, 400px = 1.6x — then clamp to a ~140ms floor and ~400ms ceiling. One `--duration-md` cannot serve an 8px tooltip nudge and a full-height sheet. This is a third axis, not a duplicate: `animations-proportional-values` scales transform AMPLITUDE, `animations-emil-duration-budget` assigns duration by element TYPE, and distance is what reconciles them (it is why drawers are the one type allowed past 300ms — a drawer is not special, it is far).
Derive duration from how far the element actually travels, sublinearly — one token cannot serve 8px and 200px
const factor = 1 + 0.3 * Math.log2(px / 100); // 100px=1x, 200px=1.3x, 400px=1.6x
const duration = Math.min(400, Math.max(140, 250 * factor));Bad
Good
Why it matters
Spend a single --duration-md: 200ms on both an 8px tooltip nudge and a full-height bottom sheet and the same number is wrong in both directions at once: the tooltip crawls the last few pixels of a journey the eye finished instantly, and the sheet covers 200px faster than the eye can track, so it reads as a teleport. Derive it instead: factor = 1 + 0.3 * log2(px / 100), giving 100px = 1×, 200px = 1.3×, 400px = 1.6× — sublinear, because doubling the distance must not double the duration or long journeys feel like wading — then clamp to a floor (~140ms) and a ceiling (~400ms).
On a 250ms base that puts the sheet at ~325ms and the tooltip at 140ms. THIS IS A THIRD AXIS, not a duplicate: animations-proportional-values (Rauno) scales the AMPLITUDE of a transform to the trigger SIZE — how far to move — and animations-emil-duration-budget assigns duration by element TYPE (press 100–160ms, tooltip 125–200ms, dropdown 150–250ms, drawer 200–500ms).
Distance is what reconciles them, and it is precisely why that budget lists drawers as the one type allowed past the 300ms ceiling: a drawer is not special, it is simply far.