Motion
Motion rules
Eight kinds of movement, each with one ease and a duration. Every animation in Octagon OS is one of them — pick the kind, and the timing comes with it.
The eight kinds
Pick one: the curve is drawn from the real GSAP ease and the dot moves with it.
power3.out · 0.55s Pages (y 18 · 0.55s), popups and menus (y −6, scale .97 · 0.3s), the palette (0.35s), list rows (y 24 · 0.6s, 40–60ms apart)
CSS transitions
Hover and colour changes stay in CSS — they are too small for a tween.
| What | Transition |
|---|---|
| Hover backgrounds and colours | background .2s · color .2s |
| Card lift shadow, legend nudge, sidebar items | .35s cubic-bezier(.2, .8, .2, 1) (--ease-out) |
| Width or padding changes (sidebar collapse) | .45s cubic-bezier(.2, .8, .2, 1) |
| Fades (tooltips leaving, dimming) | opacity .25s – .35s |
| Chart parts dimming on hover | filter .25s · opacity .3s |
The laws
Something arrived, moved, grew or left. If nothing changed, nothing moves — no idle wiggles, no looping shimmer.
Entrances 0.3–0.6s; exits about half that. People watch things come in; they don’t wait for them to go.
x, y, scale, rotation, opacity and filter. Never width, top or margin for movement (the one exception: a box springing to a new text width).
GSAP’s ticker drives Lenis and every effect. No component starts its own requestAnimationFrame loop.
A number counts from its old value, a tooltip glides from its last spot, a bar grows from its current height. Nothing snaps back to zero.
With “reduce motion” on, everything lands in its final state at once. Information never depends on animation.
Effects pause when out of view and stop their loop when they have nothing to draw.
Buttons work mid-animation; a second click re-targets the move instead of queueing behind it.