Variants
Button with Hover and Tap Effects
Example of how to use frame motion variants.
Animated Button
animated-button.tsx
import AnimatedButton from '@/components/animations/animated-button' import React from 'react' const Variants = () => { return ( <div className="p-5"> <AnimatedButton refresh className='px-6 py-3 rounded-md bg-black dark:bg-orange-500' hoverVarints={{scale:1.2, boxShadow: "0px 2px 8px rgb(0,0,0,0.2)"}} tapVariants={{scale: 0.9}}> <span className='text-white'>Click Me</span> </AnimatedButton> </div> ) } export default Variants "use client" import React, { useState } from 'react'; import { Preview } from '../common/display'; import { motion } from "framer-motion"; interface hoverProps { scale: number; boxShadow: string; } interface tapProps { scale: number; } interface AnimatedButtonProps { children: React.ReactNode; hoverVarints: hoverProps; tapVariants: tapProps; className?:string; refresh:boolean; } const AnimatedButton = ({ children, hoverVarints, tapVariants ,className, refresh}: AnimatedButtonProps) => { const [count, setCount] = useState(0); const buttonVariants = { hover: { scale: hoverVarints.scale, boxShadow: hoverVarints.boxShadow }, tap: { scale: tapVariants.scale } }; return ( <Preview SetCount={setCount} isRefreshing={refresh} animeName='AnimatedButton'> <motion.button key={count} variants={buttonVariants} whileHover="hover" whileTap="tap" className={className} > {children} </motion.button> </Preview> ) } export default AnimatedButton interface PreviewerProps { children: React.ReactNode; SetCount: (count: number) => void; isRefreshing: boolean; animeName:string hideIcon?: boolean; } export const Preview = ({ children, SetCount, isRefreshing, animeName, hideIcon=false }: PreviewerProps) => { const [count, setCount] = useState(0); const [isLoading, setIsLoading] = useState(false); const handleClick = () => { setIsLoading(true); setCount(count + 1); SetCount(count + 1); setTimeout(() => { setIsLoading(false); }, 400); // Timeout duration matches the animation duration }; return ( <div className="w-full h-full flex flex-col"> <div className="w-full flex-1 flex justify-center items-center"> {children} </div> {isRefreshing && <div className="h-[50px] w-full px-6 rounded-b-[24px] flex justify-between"> <span>{animeName}</span>{!hideIcon && <RotateCw onClick={handleClick} className={isLoading ? 'animate-spin duration-200' : 'animate-none'} />} </div> } </div> ) };