I want to animate a nextjs Link component using framer motion. I'm also using TypeScript and It keeps giving me a type error of:
Property 'Link' does not exist on type '(<Props extends {}>(Component: string | ComponentType<PropsWithChildren<Props>>, customMotionComponentConfig?: CustomMotionComponentConfig | undefined) => CustomDomComponent<...>) & HTMLMotionComponents & SVGMotionComponents'. Did you mean 'link'?
Here's the component I'm making.
export default function Button({ href, text, type, ...props }: ButtonTypes) {
console.log(styles);
if (href) {
return (
<motion.Link
href={href}
type={type}
className={`${styles['neon-button']} focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-aquamarine`}
{...props}
>
{text}
</motion.Link>
);
}
return (
<motion.button
whileHover={{ scale: 1.1 }}
whileTap={{ scale: 0.9 }}
type={type}
className="neon-button focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-aquamarine"
{...props}
>
{text}
</motion.button>
);
}
The component animates when I add the whileHover and whileTap properties, but obviously I need to get rid of the type error.
You can do so by wrapping Component in motion()
function.
const Component = React.forwardRef((props, ref) => (
<div ref={ref} />
))
const MotionComponent = motion(Component)
const MotionLink= motion(Link)
If you don't like this there are some workarounds as well:
Workaround 1: One possible work around is to wrap your next Link in a div and use framer motion on wrapper div.
<motion.div
className={styles.linkWrapper}
//your framer motion props goes here
>
<Link href="#"> Lorem </Link>
</motion.div>
--
Workaround 2:
Use <motion.a>
tag instead of <Link>
and use useRouter
to implement functionality of Link
on a
tag.
Example:
const router = useRouter()
<motion.a
href="/contact"
onClick={(e) => {
e.preventDefault();
router.push("/contact");
}}
className={styles.navLink}
>
Lorem
</motion.a>
Learn more at: Next useRouter Hook official documentation