Global configuration and feature bundle system for code splitting and performance optimization.
Provides global configuration for all motion components within its context.
/**
* Global configuration provider for motion components
* @param props - Configuration options
* @returns JSX element providing motion configuration context
*/
function MotionConfig(props: MotionConfigProps): JSX.Element;
interface MotionConfigProps {
/**
* Child components to apply configuration to
*/
children: React.ReactNode;
/**
* Default transition for all animations
*/
transition?: Transition;
/**
* Transform page coordinates (useful for zoom/pan interfaces)
*/
transformPagePoint?: (point: Point) => Point;
/**
* Reduced motion preference override
* - "always": Always reduce motion
* - "never": Never reduce motion
* - "user": Respect user's system preference (default)
*/
reducedMotion?: "always" | "never" | "user";
/**
* Custom prop validation function
*/
isValidProp?: (key: string) => boolean;
/**
* Enable/disable features globally
*/
features?: {
/**
* Enable layout animations (default: true)
*/
layout?: boolean;
/**
* Enable gesture handling (default: true)
*/
gestures?: boolean;
/**
* Enable exit animations (default: true)
*/
animations?: boolean;
};
}
interface Transition {
/**
* Animation duration in seconds
*/
duration?: number;
/**
* Delay before animation starts in seconds
*/
delay?: number;
/**
* Easing function or array for keyframes
*/
ease?: Easing | Easing[];
/**
* Animation type
*/
type?: "tween" | "spring" | "keyframes" | "inertia";
/**
* Number of times to repeat
*/
repeat?: number;
/**
* Type of repeat behavior
*/
repeatType?: "loop" | "reverse" | "mirror";
/**
* Delay between repeats
*/
repeatDelay?: number;
// Spring-specific options
bounce?: number;
damping?: number;
mass?: number;
stiffness?: number;
velocity?: number;
restSpeed?: number;
restDelta?: number;
}
interface Point {
x: number;
y: number;
}Usage Examples:
import { MotionConfig, motion } from "framer-motion";
// Global transition configuration
function GlobalTransitionExample() {
return (
<MotionConfig
transition={{
type: "spring",
stiffness: 260,
damping: 20
}}
>
<div className="space-y-4">
<motion.div
whileHover={{ scale: 1.1 }}
className="w-32 h-32 bg-blue-500 rounded"
>
Uses global spring config
</motion.div>
<motion.div
whileHover={{ scale: 1.1 }}
transition={{ type: "tween", duration: 0.2 }} // Override global
className="w-32 h-32 bg-red-500 rounded"
>
Overrides with tween
</motion.div>
</div>
</MotionConfig>
);
}
// Reduced motion configuration
function ReducedMotionExample() {
return (
<MotionConfig reducedMotion="user">
<motion.div
initial={{ opacity: 0, y: 50 }}
animate={{ opacity: 1, y: 0 }}
className="p-4 bg-green-500 text-white rounded"
>
Respects user's motion preferences
</motion.div>
</MotionConfig>
);
}
// Custom coordinate transformation
function TransformPointExample() {
const transformPagePoint = (point: Point) => ({
x: point.x * 0.5, // Scale down x coordinates
y: point.y * 0.5 // Scale down y coordinates
});
return (
<MotionConfig transformPagePoint={transformPagePoint}>
<motion.div
drag
className="w-32 h-32 bg-purple-500 rounded cursor-grab"
>
Drag coordinates are scaled
</motion.div>
</MotionConfig>
);
}Enables code splitting by loading animation features on demand.
/**
* Lazy loading wrapper for motion features
* @param props - LazyMotion configuration
* @returns JSX element providing lazy-loaded features
*/
function LazyMotion(props: LazyMotionProps): JSX.Element;
interface LazyMotionProps {
/**
* Child components that will use lazy-loaded features
*/
children: React.ReactNode;
/**
* Feature bundle to load (sync or async)
*/
features: FeatureBundle | (() => Promise<FeatureBundle>);
/**
* Strict mode - only allow features defined in bundle (default: true)
*/
strict?: boolean;
}
interface FeatureBundle {
/**
* Animation feature definitions
*/
animation?: FeatureDefinition;
/**
* Exit animation features
*/
exit?: FeatureDefinition;
/**
* Gesture handling features
*/
gestures?: FeatureDefinition;
/**
* Drag interaction features
*/
drag?: FeatureDefinition;
/**
* Layout animation features
*/
layout?: FeatureDefinition;
/**
* Measurement and projection features
*/
measureLayout?: FeatureDefinition;
}
interface FeatureDefinition {
/**
* Feature implementation functions
*/
[key: string]: any;
}Pre-built Feature Bundles:
/**
* Minimal DOM features bundle (animations only)
*/
const domMin: FeatureBundle;
/**
* DOM animation features bundle (animations + gestures)
*/
const domAnimation: FeatureBundle;
/**
* Maximum DOM features bundle (all features)
*/
const domMax: FeatureBundle;Usage Examples:
import { LazyMotion, domAnimation, domMax, m } from "framer-motion";
// Synchronous feature loading
function SyncLazyMotionExample() {
return (
<LazyMotion features={domAnimation}>
<m.div
whileHover={{ scale: 1.1 }}
whileTap={{ scale: 0.95 }}
className="w-32 h-32 bg-blue-500 rounded cursor-pointer"
>
Lazy loaded gestures
</m.div>
</LazyMotion>
);
}
// Asynchronous feature loading
function AsyncLazyMotionExample() {
return (
<LazyMotion
features={() => import("framer-motion").then(mod => mod.domMax)}
strict={false}
>
<m.div
drag
whileHover={{ scale: 1.1 }}
className="w-32 h-32 bg-green-500 rounded cursor-grab"
>
Async loaded features
</m.div>
</LazyMotion>
);
}
// Custom feature bundle
function CustomFeatureExample() {
const customFeatures = async () => {
// Load only specific features
const { domAnimation } = await import("framer-motion");
return domAnimation;
};
return (
<LazyMotion features={customFeatures}>
<m.div
animate={{ rotate: 360 }}
transition={{ duration: 2, repeat: Infinity, ease: "linear" }}
className="w-16 h-16 bg-purple-500 rounded"
>
Custom bundle
</m.div>
</LazyMotion>
);
}Global configuration utilities that affect all Framer Motion instances.
/**
* Global motion configuration object from motion-utils
*/
interface MotionGlobalConfig {
/**
* Skip animations entirely (useful for testing)
*/
skipAnimations?: boolean;
/**
* Use reduced motion globally
*/
useManualTiming?: boolean;
/**
* Custom easing functions
*/
easing?: {
[key: string]: (t: number) => number;
};
}
/**
* Access to global motion configuration
*/
const MotionGlobalConfig: MotionGlobalConfig;Usage Example:
import { MotionGlobalConfig } from "framer-motion";
// Configure globally (typically in app setup)
MotionGlobalConfig.skipAnimations = process.env.NODE_ENV === "test";
// Custom easing functions
MotionGlobalConfig.easing = {
...MotionGlobalConfig.easing,
customEase: (t: number) => t * t * (3 - 2 * t) // Smoothstep
};
function GlobalConfigExample() {
return (
<motion.div
animate={{ x: 100 }}
transition={{ ease: "customEase", duration: 1 }}
>
Uses custom global easing
</motion.div>
);
}Hooks for detecting and responding to reduced motion preferences.
/**
* Detect user's reduced motion preference
* @returns Boolean indicating if reduced motion is preferred
*/
function useReducedMotion(): boolean;
/**
* Configure reduced motion behavior for components
* @returns Configuration object for reduced motion
*/
function useReducedMotionConfig(): {
/**
* Whether reduced motion is currently active
*/
shouldReduceMotion: boolean;
/**
* Override reduced motion setting
*/
setReducedMotion: (reduce: boolean | "user") => void;
};Usage Examples:
import { motion, useReducedMotion, useReducedMotionConfig } from "framer-motion";
// Basic reduced motion detection
function ReducedMotionExample() {
const shouldReduceMotion = useReducedMotion();
return (
<motion.div
animate={{
x: shouldReduceMotion ? 0 : 100,
transition: {
duration: shouldReduceMotion ? 0 : 1
}
}}
className="w-32 h-32 bg-blue-500 rounded"
>
Motion respects user preference
</motion.div>
);
}
// Advanced reduced motion configuration
function AdvancedReducedMotionExample() {
const { shouldReduceMotion, setReducedMotion } = useReducedMotionConfig();
return (
<div>
<div className="mb-4 space-x-2">
<button
onClick={() => setReducedMotion(false)}
className="px-4 py-2 bg-blue-500 text-white rounded"
>
Enable Motion
</button>
<button
onClick={() => setReducedMotion(true)}
className="px-4 py-2 bg-red-500 text-white rounded"
>
Disable Motion
</button>
<button
onClick={() => setReducedMotion("user")}
className="px-4 py-2 bg-gray-500 text-white rounded"
>
Respect User Preference
</button>
</div>
<motion.div
animate={{
rotate: shouldReduceMotion ? 0 : 360,
scale: shouldReduceMotion ? 1 : [1, 1.2, 1]
}}
transition={{
duration: shouldReduceMotion ? 0 : 2,
repeat: shouldReduceMotion ? 0 : Infinity
}}
className="w-32 h-32 bg-green-500 rounded"
>
Configurable motion
</motion.div>
<p className="mt-2 text-sm">
Reduced motion: {shouldReduceMotion ? "Active" : "Inactive"}
</p>
</div>
);
}Utilities for detecting available features and capabilities.
/**
* Check if running in browser environment
* @returns Boolean indicating browser environment
*/
function isBrowser(): boolean;
/**
* Detect available animation features
* @returns Object describing available features
*/
interface FeatureDetection {
/**
* Web Animations API support
*/
waapi: boolean;
/**
* CSS transforms support
*/
transforms: boolean;
/**
* Touch/pointer events support
*/
touch: boolean;
/**
* Reduced motion preference
*/
reducedMotion: boolean;
}
/**
* Browser environment detection
*/
const isBrowser: boolean;Usage Example:
import { isBrowser } from "framer-motion";
import { useEffect, useState } from "react";
function FeatureDetectionExample() {
const [features, setFeatures] = useState<any>(null);
useEffect(() => {
if (isBrowser()) {
// Detect browser capabilities
const detection = {
waapi: "animate" in document.createElement("div"),
transforms: "transform" in document.createElement("div").style,
touch: "ontouchstart" in window,
reducedMotion: window.matchMedia("(prefers-reduced-motion: reduce)").matches
};
setFeatures(detection);
}
}, []);
if (!isBrowser()) {
return <div>Server-side rendering</div>;
}
return (
<div>
<h3>Browser Capabilities:</h3>
{features && (
<ul className="list-disc pl-6">
<li>Web Animations API: {features.waapi ? "✅" : "❌"}</li>
<li>CSS Transforms: {features.transforms ? "✅" : "❌"}</li>
<li>Touch Support: {features.touch ? "✅" : "❌"}</li>
<li>Reduced Motion: {features.reducedMotion ? "✅" : "❌"}</li>
</ul>
)}
</div>
);
}Configuration options for optimizing animation performance.
/**
* Configure performance settings
*/
interface PerformanceConfig {
/**
* Enable GPU acceleration hints
*/
useGPUAcceleration?: boolean;
/**
* Batch DOM updates
*/
batchUpdates?: boolean;
/**
* Throttle animation frame rate
*/
maxFrameRate?: number;
/**
* Enable transform optimization
*/
optimizeTransforms?: boolean;
}Usage Example:
// Configure performance at app level
function App() {
return (
<MotionConfig
transition={{
type: "spring",
stiffness: 260,
damping: 20
}}
>
<LazyMotion features={domAnimation}>
<div className="app">
{/* App content with optimized motion */}
</div>
</LazyMotion>
</MotionConfig>
);
}
// Environment-specific configuration
const getMotionConfig = () => {
if (process.env.NODE_ENV === "development") {
return { reducedMotion: "never" }; // Always animate in dev
}
if (process.env.NODE_ENV === "test") {
MotionGlobalConfig.skipAnimations = true; // Skip in tests
}
return { reducedMotion: "user" }; // Respect user preference in production
};Responsive Motion:
function ResponsiveMotion() {
const [isMobile, setIsMobile] = useState(false);
useEffect(() => {
const checkMobile = () => setIsMobile(window.innerWidth < 768);
checkMobile();
window.addEventListener("resize", checkMobile);
return () => window.removeEventListener("resize", checkMobile);
}, []);
return (
<MotionConfig
transition={{
type: isMobile ? "tween" : "spring",
duration: isMobile ? 0.2 : 0.6
}}
>
{/* Motion components adapt to screen size */}
</MotionConfig>
);
}Theme-based Configuration:
function ThemedMotion({ theme, children }: { theme: "light" | "dark", children: React.ReactNode }) {
const config = {
light: {
transition: { type: "spring", stiffness: 300 },
reducedMotion: "user"
},
dark: {
transition: { type: "tween", duration: 0.3 },
reducedMotion: "never"
}
};
return (
<MotionConfig {...config[theme]}>
{children}
</MotionConfig>
);
}Progressive Enhancement:
function ProgressiveMotion({ children }: { children: React.ReactNode }) {
const [features, setFeatures] = useState(domMin);
useEffect(() => {
// Progressively load more features
const loadFullFeatures = async () => {
const { domMax } = await import("framer-motion");
setFeatures(domMax);
};
// Load after initial render
const timer = setTimeout(loadFullFeatures, 100);
return () => clearTimeout(timer);
}, []);
return (
<LazyMotion features={features}>
{children}
</LazyMotion>
);
}