Like Button

Using Framer Motion we can create this nice transition effect, making the tabs stand out from your ordinary component

'use client'
import { motion, Variants } from 'framer-motion'
import React from 'react'
import { cn } from '@/utils'
type LikeButtonProps = {
count: number
}
const variants: Variants = {
rest: {
transition: { duration: 0.7 },
},
hover: {
scale: 1.2,
y: -8,
},
press: { scale: 1.1 },
}
export function LikeButton({ count }: LikeButtonProps) {
const [isLiked, setIsLiked] = React.useState<0 | 1 | 2 | 3>(0)
const [isHover, setIsHover] = React.useState(false)
const isResetDisabled = isLiked === 0
const onClick = () => {
setIsLiked(last => {
if (last === 0) {
return 1
}
if (last === 1) {
return 2
}
return 3
})
}
return (
<motion.button
initial={false}
animate={isHover ? 'hover' : 'rest'}
whileTap={'press'}
variants={variants}
onHoverStart={() => setIsHover(true)}
onHoverEnd={() => setIsHover(false)}
onClick={onClick}
className={cn('flex appearance-none items-center rounded-3xl shadow-xl transition-shadow hover:shadow-2xl', {
'bg-white': true,
})}>
<div className={'pl-6 text-2xl font-semibold'}>
// Heart
<svg width={'36'} height={'36'} viewBox={'0 0 64 64'} fill={'none'} xmlns={'http://www.w3.org/2000/svg'}>
<g id={'heart'}>
<mask
id={'mask0_0_1'}
style={{ maskType: 'alpha' }}
maskUnits={'userSpaceOnUse'}
x={'4'}
y={'8'}
width={'56'}
height={'48'}>
<path
id={'stroke_2'}
d={
'M32 13.9725C34.8175 10.22 39.3375 8 44.5 8C48.6094 8.00463 52.5492 9.63915 55.455 12.545C58.3609 15.4508 59.9954 19.3906 60 23.5C60 41 34.0525 55.165 32.9475 55.75C32.6563 55.9067 32.3307 55.9887 32 55.9887C31.6693 55.9887 31.3437 55.9067 31.0525 55.75C29.9475 55.165 4 41 4 23.5C4.00463 19.3906 5.63915 15.4508 8.54496 12.545C11.4508 9.63915 15.3906 8.00463 19.5 8C24.6625 8 29.1825 10.22 32 13.9725Z'
}
className={'fill-black'}
/>
</mask>
<g mask={'url(#mask0_0_1)'}>
<path
id={'stroke_1'}
d={
'M32 13.9725C34.8175 10.22 39.3375 8 44.5 8C48.6094 8.00463 52.5492 9.63915 55.455 12.545C58.3609 15.4508 59.9954 19.3906 60 23.5C60 41 34.0525 55.165 32.9475 55.75C32.6563 55.9067 32.3307 55.9887 32 55.9887C31.6693 55.9887 31.3437 55.9067 31.0525 55.75C29.9475 55.165 4 41 4 23.5C4.00463 19.3906 5.63915 15.4508 8.54496 12.545C11.4508 9.63915 15.3906 8.00463 19.5 8C24.6625 8 29.1825 10.22 32 13.9725Z'
}
fill={'url(#paint0_linear_0_1)'}
/>
<motion.rect
initial={false}
animate={isLiked.toString()}
variants={{
'0': { translateY: '75%' },
'1': { translateY: '50%' },
'2': { translateY: '25%' },
'3': { translateY: '0%' },
}}
id={'background'}
width={'65'}
height={'65'}
fill={'url(#paint1_linear_0_1)'}
/>
</g>
</g>
<defs>
<linearGradient
id={'paint0_linear_0_1'}
x1={'4'}
y1={'32'}
x2={'60'}
y2={'32'}
gradientUnits={'userSpaceOnUse'}>
<stop stopColor={'#E5E5E5'} />
</linearGradient>
<linearGradient
id={'paint1_linear_0_1'}
x1={'4.84288e-07'}
y1={'81.5'}
x2={'65'}
y2={'81.5'}
gradientUnits={'userSpaceOnUse'}>
<stop stopColor={'#FD367A'} />
<stop offset={'0.340475'} stopColor={'#FE7FA6'} />
<stop offset={'0.665229'} stopColor={'#FEB7B9'} />
<stop offset={'1'} stopColor={'#FFA48D'} />
</linearGradient>
</defs>
</svg>
</div>
<div className={'pl-4 pr-6 text-2xl font-semibold transition-colors'}>Like me!</div>
<div
className={cn('rounded-r-3xl border-l-2 border-l-neutral-100 px-6 py-4 text-2xl font-semibold', {
'text-neutral-200': isResetDisabled,
})}>
{count + isLiked}
</div>
</motion.button>
)
}