Chakra UI + Framer Motion

If you'd like to add some interesting motion interaction or animation to your Chakra UI websites or apps, here's a quick tip:

If you're using a version of framer motion less than v 3.10.0:

import { Box, forwardRef } from "@chakra-ui/react"
import { motion, isValidMotionProp } from "framer-motion"
// 1. Create a custom motion component from Box
const MotionBox = motion.custom(
forwardRef((props, ref) => {
const chakraProps = Object.fromEntries(
// do not pass framer props to DOM element
Object.entries(props).filter(([key]) => !isValidMotionProp(key)),
)
return <Box ref={ref} {...chakraProps} />
}),
)
// 2. You'll get access to `motion` and `chakra` props in `MotionBox`
function Example() {
return (
<MotionBox
boxSize="40px"
bg="red.300"
drag="x"
dragConstraints={{ left: -100, right: 100 }}
whileHover={{ scale: 1.1 }}
whileTap={{ scale: 0.9 }}
/>
)
}
Edit with CodeSandbox

If you're using the latest verion of framer motion, which is >= v 3.10.0. In this version, framer-motion automatically filters out motion-related props forwarded to the provided component. Reference

import { Box, forwardRef } from "@chakra-ui/react"
import { motion } from "framer-motion"
const MotionBox = motion(Box)
function Example() {
return (
<MotionBox
height="40px"
bg="red.300"
drag="x"
dragConstraints={{ left: -100, right: 100 }}
whileHover={{ scale: 1.1 }}
whileTap={{ scale: 0.9 }}
/>
)
}

For TypeScript users, here's what you need to do:

import React from "react"
import { HTMLChakraProps, chakra } from "@chakra-ui/react"
import { motion, HTMLMotionProps } from "framer-motion"
type Merge<P, T> = Omit<P, keyof T> & T;
type MotionBoxProps = Merge<HTMLChakraProps<"div">, HTMLMotionProps<"div">>;
export const MotionBox: React.FC<MotionBoxProps> = motion(chakra.div);
function Example() {
return (
<MotionBox
height="40px"
bg="red.300"
drag="x"
dragConstraints={{ left: -100, right: 100 }}
whileHover={{ scale: 1.1 }}
whileTap={{ scale: 0.9 }}
/>
)
}
Edit with CodeSandbox