Motion System: Shopify Polaris
Category: E-commerce / Design System Calm, confidence-inspiring motion that keeps merchants in flow — present when needed, invisible when not.
Motion Philosophy
Shopify Polaris is built around a single insight: merchants are working. They are fulfilling orders, resolving disputes, updating inventory, and running businesses under real-world pressure. Motion in Polaris is not about making the product feel modern or impressive — it is about reducing anxiety. Every animation should make the interface feel more predictable, more stable, and more trustworthy. If an animation draws attention to itself, it has failed.
Polaris describes its motion as "calm." This means preferring ease-out over ease-in-out (which can feel playful), keeping durations in the 100–300ms range for the vast majority of transitions, and never using bounce or spring effects in core merchant workflows. A merchant who has just processed 200 orders in a row should not be surprised by a tooltip that wobbles. Confidence is built through consistency: every transition in Polaris feels like it belongs to the same system.
Accessibility is a first-class concern, not an afterthought. Polaris documents prefers-reduced-motion handling explicitly in its motion guidelines, and all animation must degrade gracefully. This means structuring transitions so that removing duration and transform still leaves a functional, legible state change — typically a bare opacity transition at 100ms or a direct cut. Many Polaris merchants use assistive technology or work in environments where vestibular sensitivity is a concern.
Duration Scale
| Token | Value | Use |
|---|---|---|
| instant | 0ms | State changes with no visual transition |
| fast | 100ms | Hover states, focus rings, small icon transitions, toggle switches |
| default | 200ms | Most UI transitions — dropdowns, popovers, badge updates |
| slow | 300ms | Modal open/close, page-level banners, large content shifts |
| slower | 500ms | Onboarding callouts, empty state illustrations entering |
Easing
| Token | Curve | Use |
|---|---|---|
| ease-out | cubic-bezier(0.25, 0, 0, 1) | Elements entering — the primary Polaris easing |
| ease-in | cubic-bezier(0.42, 0, 1, 1) | Elements exiting the screen |
| ease-in-out | cubic-bezier(0.42, 0, 0, 1) | Elements repositioning within the layout |
| linear | cubic-bezier(0, 0, 1, 1) | Loading spinners, progress bars |
Polaris strongly prefers ease-out. The deceleration curve communicates that the system is responding decisively — elements arrive with momentum and settle, rather than accelerating out of the way.
Spring Configs (Framer Motion / react-spring)
Polaris core components do not use spring physics. The Polaris design token system is built on deterministic cubic-bezier curves to ensure consistent behavior across browsers and animation libraries.
For product teams building custom experiences on top of Polaris who choose to use springs, Polaris recommends conservative, overdamped values:
- Conservative (closest to Polaris feel): stiffness: 300, damping: 40, mass: 1
- Gentle (for decorative illustrations only): stiffness: 180, damping: 22, mass: 1
Do not use springs for any interactive feedback in merchant-critical flows (checkout, order management, payment processing).
Stagger Patterns
- List items: 30ms between each item, max 8 items staggered
- Cards in grid: 40ms between each card, max 6 cards
- Nav items: No stagger — navigation must feel instant
- Action list items (dropdowns): 20ms between items, capped at 5 items (beyond 5, no stagger)
Enter / Exit Patterns
Fade + Slide (default)
enter: opacity 0→1, translateY 8px→0, duration: default (200ms), ease: ease-out
exit: opacity 1→0, translateY 0→-4px, duration: fast (100ms), ease: ease-in
Scale Pop (popovers, tooltips, action menus)
enter: opacity 0→1, scale 0.96→1, duration: fast (100ms), ease: ease-out
exit: opacity 1→0, scale 1→0.96, duration: fast (100ms), ease: ease-in
Modal / Full-screen overlay
enter: opacity 0→1, translateY 16px→0, duration: slow (300ms), ease: ease-out
exit: opacity 1→0, translateY 0→8px, duration: default (200ms), ease: ease-in
Banner / Toast notification
enter: opacity 0→1, translateY -100%→0 (top banners), duration: default (200ms), ease: ease-out
exit: opacity 1→0, duration: fast (100ms), ease: ease-in
Skeleton loading
shimmer: background-position animates left→right, duration: 1800ms, ease: linear, loop: infinite
Interaction States
- Hover: Background tint shift over 100ms ease-out. No scale transforms on interactive controls. Subtle scale (1→1.02) is acceptable only on product image cards. Cursor feedback is the primary hover signal.
- Press/Active: Background darkens immediately (0ms) on mousedown/touchstart. This instant feedback is critical — merchants need to know the system registered their input without waiting for animation.
- Focus: Focus ring appears at 0ms (no animation). Polaris uses a
--p-focusedbox-shadow that must be immediately visible for keyboard navigation. The ring is never animated in or out. - Loading: Spinner uses 500ms linear rotation loop. Skeleton screens preferred over spinners for content areas larger than a single line. Skeleton shimmer is a linear animation — no ease, consistent speed.
- Reduced motion: When
prefers-reduced-motion: reduce, all transforms are removed and durations are cut to 0ms. Opacity-only transitions are kept at 100ms max. Skeleton shimmer animation stops; static skeleton state shown instead.
Rules
- Motion must serve merchant confidence, not brand expression. If an animation could be removed with no loss of usability, remove it.
- Never use bounce, elastic, or spring easing in core merchant workflows. Reserve any experimental motion for marketing or onboarding surfaces, and test with merchant focus groups first.
- Always implement
prefers-reduced-motion. This is a hard requirement in Polaris, not a recommendation. Test every animated component with reduced motion before shipping. - Exits are always faster than entrances. Merchants should never feel that the UI is slow to close or get out of the way.
- Do not animate more than one large region simultaneously. If a modal opens and a toast appears at the same moment, delay the toast by 200ms to prevent competing motion.