Motion
Motion in Synchronicity is inspired by breath—organic, rhythmic, and calming. Animations should feel natural, never jarring or rushed.
Philosophy
Section titled “Philosophy”“Movement follows stillness; stillness follows movement.”
Our motion system embodies three principles:
- Purposeful - Every animation serves a function
- Organic - Movements feel natural, not mechanical
- Contemplative - Timing encourages mindfulness
Duration Scale
Section titled “Duration Scale”instant100msMicro-interactions, toggles
fast200msButton feedback, hover states
normal300msStandard transitions
slow500msPage transitions, modals
slower700msComplex reveals, emphasis
slowest1000msMeditative transitions
Breathing Rhythm
Section titled “Breathing Rhythm”The signature animation pattern of Synchronicity follows human breathing:
const breathing = { inhale: 3600, // 3.6 seconds - building, gathering hold: 1200, // 1.2 seconds - stillness, peak exhale: 4800, // 4.8 seconds - release, calm total: 9600, // Complete cycle};This 9.6-second cycle creates a meditative rhythm suitable for:
- Loading states
- Background animations
- Ambient UI elements
- Transition sequences
Easing Functions
Section titled “Easing Functions”CSS Easings
Section titled “CSS Easings”const easing = { linear: 'linear', easeIn: 'cubic-bezier(0.4, 0, 1, 1)', easeOut: 'cubic-bezier(0, 0, 0.2, 1)', easeInOut: 'cubic-bezier(0.4, 0, 0.2, 1)',
// Contemplative easings gentleIn: 'cubic-bezier(0.25, 0.1, 0.25, 1)', gentleOut: 'cubic-bezier(0.25, 0.1, 0.25, 1)', breath: 'cubic-bezier(0.45, 0, 0.55, 1)',};Spring Motion (React Native)
Section titled “Spring Motion (React Native)”For more organic, physics-based animations:
const spring = { gentle: { damping: 20, stiffness: 100, mass: 1, }, bouncy: { damping: 10, stiffness: 150, mass: 0.8, }, stiff: { damping: 30, stiffness: 300, mass: 0.5, }, slow: { damping: 25, stiffness: 80, mass: 1.2, },};Animation Patterns
Section titled “Animation Patterns”Fade In
Section titled “Fade In”For elements appearing on screen:
import { useTheme } from '@synchronicity/react-native';import Animated, { useAnimatedStyle, withTiming} from 'react-native-reanimated';
function FadeIn({ children }) { const { motion } = useTheme();
const style = useAnimatedStyle(() => ({ opacity: withTiming(1, { duration: motion.duration.normal, easing: motion.easing.easeOut, }), }));
return ( <Animated.View style={[{ opacity: 0 }, style]}> {children} </Animated.View> );}.fade-in { animation: fadeIn 300ms cubic-bezier(0, 0, 0.2, 1) forwards;}
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; }}Scale Entrance
Section titled “Scale Entrance”For cards and modals:
const scaleIn = { from: { opacity: 0, transform: [{ scale: 0.95 }], }, to: { opacity: 1, transform: [{ scale: 1 }], }, config: { duration: 300, easing: 'easeOut', },};Breathing Pulse
Section titled “Breathing Pulse”For meditative loading states:
function BreathingPulse() { const { motion } = useTheme(); const opacity = useSharedValue(0.4);
useEffect(() => { opacity.value = withRepeat( withSequence( // Inhale withTiming(1, { duration: motion.breathing.inhale }), // Hold withDelay(motion.breathing.hold, withTiming(1, { duration: 0 })), // Exhale withTiming(0.4, { duration: motion.breathing.exhale }) ), -1, // Infinite false ); }, []);
return ( <Animated.View style={{ opacity }}> {/* Content */} </Animated.View> );}Usage Guidelines
Section titled “Usage Guidelines”- Use
easeOutfor elements entering the screen - Use
easeInfor elements leaving the screen - Use
springfor gesture-driven animations - Use breathing rhythm for ambient, continuous animations
- Keep UI feedback animations under 300ms
- Use linear easing for UI transitions (feels mechanical)
- Make users wait through long animations
- Animate multiple things at once without choreography
- Use bouncy springs for serious/contemplative contexts
Reduced Motion
Section titled “Reduced Motion”Always respect user preferences for reduced motion:
import { useReducedMotion } from 'react-native-reanimated';
function AnimatedComponent() { const reducedMotion = useReducedMotion(); const { motion } = useTheme();
const duration = reducedMotion ? 0 : motion.duration.normal;
// Use duration in animations}Motion Tokens Reference
Section titled “Motion Tokens Reference”export const motion = { duration: { instant: 100, fast: 200, normal: 300, slow: 500, slower: 700, slowest: 1000, }, breathing: { inhale: 3600, hold: 1200, exhale: 4800, total: 9600, }, easing: { linear: 'linear', easeIn: 'cubic-bezier(0.4, 0, 1, 1)', easeOut: 'cubic-bezier(0, 0, 0.2, 1)', easeInOut: 'cubic-bezier(0.4, 0, 0.2, 1)', breath: 'cubic-bezier(0.45, 0, 0.55, 1)', }, spring: { gentle: { damping: 20, stiffness: 100, mass: 1 }, bouncy: { damping: 10, stiffness: 150, mass: 0.8 }, stiff: { damping: 30, stiffness: 300, mass: 0.5 }, slow: { damping: 25, stiffness: 80, mass: 1.2 }, },};