Botim moves with one heartbeat: a soft, rhythmic pulse. Calm, trustworthy, never flashy.
A defined primitive, a cross-platform token spec, six patterns you can operate — all live on this page.
Purposeful, not decorative. Every animation has a job — guide, confirm, explain. Motion that only performs gets cut.
Calm confidence. One soft beat per event. Nothing loops but loading; money commits without overshoot.
Bilingual by construction. Energy travels in reading order. Direction is an input — physics never flips.
Feel the physics
Cross-platform values are physical conversions, not eyeballs: response = 2π/√k, ζ = c/2√k. The curve you just watched lands identically in SwiftUI and Compose.
One spec, three platforms
| Token | Spec | Web · Framer Motion |
|---|---|---|
pulse/beat the signature — arrivals & confirmations | scale 1→1.02→1 · dim 10% · 600ms | animate: scale [1, 1.02, 1] · 0.6s easeInOut |
pulse/loop loading — the beat, repeated | beat every 1.1s · ∞ · stops on resolve | repeat: Infinity · 1.1s easeInOut |
spring/gentle · 290/24 sheets, modals, large surfaces | ζ 0.70 — soft, settled | spring(stiffness: 290, damping: 24) |
spring/standard · 380/21 list items, cards, chips | ζ 0.54 — lively, quick | spring(stiffness: 380, damping: 21) |
spring/pop · 420/17 toasts, badges, small arrivals | ζ 0.41 — visible bounce | spring(stiffness: 420, damping: 17) |
spring/committed · 300/32 money moments — send, confirm, settle | ζ 0.92 — no overshoot, ever | spring(stiffness: 300, damping: 32) |
stagger/relay group arrivals — energy handed on | 80ms per element | delay: i * 0.08 |
fade/quick non-spatial fades | 200ms ease-out | tween 0.2s easeOut |
fade/backdrop dim layers behind sheets | 350ms ease-out | tween 0.35s easeOut |
exit/all everything leaves faster than it arrived | 180ms ease-in | tween 0.18s easeIn |
glow/once arrival emphasis — never loops | 550ms · single pulse of light | boxShadow keyframes · 0.55s easeOut |
Patterns, live
Button press
use Ripple confirms the touch; confirm = one beat + glow.
avoid Passive rows — a list is not a button.
List stagger
use Rows relay at 80ms; the group closes with a soft beat.
avoid Re-running the relay on sort, or past the first viewport.
Modal / sheet
use In on spring/gentle, content answers with a beat; out in 180ms.
avoid Using a sheet for navigation — that’s a page transition.
Page transition
use Surface first; content relays in; the hero block beats once.
avoid Sliding tab switches — peers crossfade, only hierarchy slides.
Loading
use pulse/loop — the signature repeated; stops the instant data lands.
avoid Anything under 300ms, and fake progress of any kind.
Success / error
use Success beats once and glows; the check lands committed.
avoid Errors never breathe — no pulse, no bounce, no glow.
Do / don’t
Motion that reads Arabic
flips entry direction · relay geometry · progress · navigation
never the pulse · springs · scale · glow — physics has no reading direction
Ship it
Pulse won a four-way live bake-off against Connected Flow, Trust Settle, and Detent. The lab is still live →