Motion

Guidelines for using motion purposefully, accessibly, and consistently across Customer.io interfaces.


Introduction

Motion is a powerful tool that brings our interfaces to life and guides users through their journey. When used thoughtfully, motion reduces cognitive load, provides essential feedback, and adds personality to the Customer.io experience. These guidelines ensure motion is purposeful, accessible, and aligned with our design principles.

Motion in our platform today

The animation system is fragmented across multiple approaches: global CSS keyframes, Ember Animated for complex transitions, Vanilla Extract for CSS-in-JS, and native SVG animations. There's no single unified animation framework, though the Visual Workflow Builder has the most sophisticated centralized configuration via ANIMATION_CONFIG. More here


Core Principles

1. Purposeful

Every animation must serve a clear function. Motion should guide users, provide feedback, or clarify relationships between elements. It never exists purely for decoration.

2. Responsive

Motion should make interfaces feel immediate and alive. User actions should receive instant visual feedback that's both seen and felt.

3. Efficient

Animations should be quick enough to feel snappy but slow enough to be perceived. They should enhance workflow, not slow it down.

4. Accessible

Motion must work for everyone. Always provide alternatives and respect user preferences for reduced motion.


Motion Styles

Customer.io uses two distinct motion styles to match different moments in the user experience:

⚡ Productive Motion

Use for: Day-to-day tasks, data entry, navigation, and workflow actions

Productive motion is subtle, efficient, and stays out of the way. It creates a sense of responsiveness while helping users focus on completing their tasks.

Characteristics:

  • Fast and snappy
  • Minimal exaggeration
  • Supports task completion
  • Feels professional and efficient

Examples: Button states, dropdown menus, toggling settings, data table sorting, revealing additional information

✨ Expressive Motion

Use for: Important moments, primary actions, celebrations, and system communications

Expressive motion is more visible and enthusiastic. It captures attention during significant moments and adds personality to key interactions.

Characteristics:

  • More pronounced movement
  • Draws attention
  • Creates emotional connections
  • Memorable and engaging

Examples: Completing a campaign, successful data import, opening a new feature, important notifications, onboarding celebrations


Easing Curves

Easing curves define how motion accelerates and decelerates. Natural motion speeds up quickly and slows down smoothly like objects in the physical world.

Standard Easing

When to use: Elements visible from beginning to end of motion

Productive: cubic-bezier(0.2, 0, 0.38, 0.9)

Expressive: cubic-bezier(0.4, 0.14, 0.3, 1)

Examples: Expanding panels, sorting table rows, transforming components

Entrance Easing

When to use: Elements entering the view

Productive: cubic-bezier(0, 0, 0.38, 0.9)

Expressive: cubic-bezier(0, 0, 0.3, 1)

Examples: Modal appearing, toaster notifications, dropdown opening, tooltip revealing

Exit Easing

When to use: Elements leaving the view permanently

Productive: cubic-bezier(0.2, 0, 1, 0.9)

Expressive: cubic-bezier(0.4, 0.14, 1, 1)

Examples: Closing modals, dismissing notifications, removing items

Exception: For elements that stay nearby (like side panels that slide off-screen but remain accessible), use standard easing instead of exit easing to imply they're ready to return.


Duration

Duration should be dynamic based on the distance traveled and the size of the animated element. Larger movements take longer; smaller movements are quicker.

Duration Tokens

table
TokenUse CaseValue
duration-fast-01Micro-interactions (buttons, toggles)70ms
duration-fast-02Micro-interactions (fades)110ms
duration-moderate-01Small movements, short distances150ms
duration-moderate-02Medium expansion, toasts240ms
duration-slow-01Large expansion, important notifications400ms
duration-slow-02Background dimming, full-screen transitions700ms

Guidelines

  • Micro-interactions should fall within 90-120ms
  • Most standard UI animations should be 150-240ms
  • Reserve longer durations (400ms+) for significant transitions
  • Scale duration with distance: larger movements = longer duration

Common Patterns

Button Interactions

Duration: 70-110ms

Easing: Entrance (productive)

Motion: Subtle scale change or color shift on hover/press

Duration: 150ms

Easing: Entrance (productive)

Motion: Fade in with slight vertical movement

Duration: 240ms

Easing: Entrance (expressive)

Motion: Fade in background overlay, scale up modal with slight upward movement

Notifications/Toasts

Duration: 240ms

Easing: Entrance (expressive) on appear, Exit (expressive) on dismiss

Motion: Slide in from edge with fade, slide out on dismiss

Page Transitions

Duration: 240-400ms

Easing: Standard (productive)

Motion: Smooth cross-fade or slide between views


How animation is handled in our platform today

Animation Systems Overview

1. Global CSS Keyframe Animations

The codebase defines reusable CSS keyframe animations in a central stylesheet: animations.scss:1-90

These include:

  • flash - opacity pulsing effect
  • shake - horizontal shake animation
  • flash-single - single flash effect
  • drop-fade-below/above - vertical slide + fade
  • flyout-right - horizontal slide + fade
  • fade-in - simple opacity transition

2. Ember Animated (Visual Workflow Builder)

The Visual Workflow Builder uses ember-animated for complex component transitions: index.gts:135-146

Animation Configuration: Centralized timing/easing values are defined in ANIMATION_CONFIG: index.gts:1898-1916

This includes configurations for:

  • Panel show/hide animations
  • Toolbar expand/collapse
  • Content transitions
  • Flyout animations

Key Animation Patterns:

  • Panel transitions: Use translateMoveFade with configurable offsets and timing index.gts:1914-1916
  • Content changes: Fade in/out with right-alignment preservation index.gts:1919-1945
  • Node transitions: Handle viewport-aware animations with zoom/scroll adjustments index.gts:1985-2010

3. Vanilla Extract CSS-in-JS (Segment Builder)

The segment/audience builder uses @vanilla-extract/css for programmatic animations: expanded.css.ts:1-77

Animation approach:

  • CSS variables for dynamic width values expanded.css.ts:11-12
  • Keyframe animations for expand/collapse/focus states expanded.css.ts:15-53
  • 0.3s duration with ease-in-out timing expanded.css.ts:67-68

4. Component-Specific Animations

  • Side Panel Sections: Collapsible sections with configurable expand/collapse timing: section.gts:317-334
  • Info Panel: Complex multi-sprite transitions with beacons for smooth element morphing: index.gts:119-176
  • Toolbar: Container resize animations with expand/collapse states: index.gts:121-134
  • Sparkles Effect: Continuous pulse animation for decorative elements: index.css.ts:4-39

5. SVG Animations

The Octopus integration uses native SVG animateMotion with dynamic timing: index.gts:43-78

6. Testing Support

Animation tests use ember-animated/test-support with accelerated playback: actions-test.ts:18-25

Tests wait for animationsSettled() before assertions: favorites-test.ts:109-110

Notes

In the separate customerio/hydra repo, there's a React-based help sidebar using Framer Motion with reduced motion support: index.tsx:35-62 This suggests the organization uses different animation libraries across different frontend stacks (Ember vs React).

The animation system is fragmented across multiple approaches: global CSS keyframes, Ember Animated for complex transitions, Vanilla Extract for CSS-in-JS, and native SVG animations. There's no single unified animation framework, though the Visual Workflow Builder has the most sophisticated centralized configuration via ANIMATION_CONFIG.