Design system/Foundations
Motion
Motion in Flowra is short and explains something: where it came from, where it went, and whether it did its job. Five curves and a few durations make up all of it.
In codeapp/globals.csslib/use-reveal.tscomponents/text-field.tsx
Curves
Tap "Play" to see each curve along a path. "Ease out" is the most used; "Spring" is for things that should feel a little alive, and "Sheet" is the same curve iOS sheets use.
0.3–0.5s The most-used curve, for sections and panels entering: starts fast and settles gently.
0.28–0.3s Overshoots the target slightly and comes back: dialogs opening on desktop and the switch handle.
0.24–0.34s The iOS sheet curve: dialogs and menus rising from the bottom on phones.
0.4s Toasts entering from the bottom; they exit in 0.35 seconds with ease.
0.18s Moving a field's floating label.
Durations
0.15sPress: 0.06s0.25s0.18s0.3sPhone: 0.34s0.24s0.4sStays: 3.6s1.35sPress feedback
A button rises 1px under the pointer and shrinks to 97 percent under a finger; a pill shrinks to 94 percent. A large button (btn-lg) doesn't rise, it only shrinks, because on screens like sign-in it's the page's only job and shouldn't jitter under the pointer.
Section entrance
On the public site, useReveal adds the is-in class the first time a section is seen and then stops watching it; a section that animates again on every scroll is distracting. The class is written directly on the node, without re-rendering anything.
Rules
Your device: ·
@media (prefers-reduced-motion: reduce)Do
A keyframe that starts from opacity zero should write to explicitly.
Don't
A keyframe with only from; it goes from zero to zero and nothing shows.
Do
JavaScript motion should check prefers-reduced-motion before starting.
Don't
Relying on the global CSS rule for an animation built with requestAnimationFrame.
Every motion, precisely
all 0.15s easePress 0.06s · scale(0.97)0.15s · scale(0.94)dropIn 0.24s cubic-bezier(0.34, 1.56, 0.64, 1)From translateY(-8px) scale(0.96)dropIn 0.2s cubic-bezier(0.34, 1.56, 0.64, 1)popIn 0.3s cubic-bezier(0.34, 1.56, 0.64, 1)From scale(0.5), opacity 0fadeInFlat 0.2s easemodalSheetUp 0.34s cubic-bezier(0.32, 0.72, 0, 1)sheetUp 0.24s cubic-bezier(0.32, 0.72, 0.25, 1)toastIn 0.4s cubic-bezier(0.16, 1, 0.3, 1)Exit toastOut 0.35s ease0.28s cubic-bezier(0.34, 1.56, 0.64, 1)0.28s spring · scale(1.35)0.22s spring · rotate(180deg)0.18s cubic-bezier(0.4, 0, 0.2, 1)stroke 0.25s easeknShimmer 1.3s ease-in-out infinitespin 0.6s linear infinite0.35s cubic-bezier(0.32, 0.72, 0.25, 1)Phone, scrolling downWith reduced motion
animation/transition-duration: 0.01ms !importantmodalFadeIn 0.18s easeInstead of sliding upanimation: noneDoes not runmatchMedia before startingDo
Enter with a soft curve, exit shorter with ease.
Don't
An exit longer than the entrance; people end up waiting for it to leave.
Do
Springy only for small things: menus, switches, icons.
Don't
Springy on a full-width sheet; the whole screen wobbles.
Related pages