Gooey Button
October 2024
TSX
interface IconProps {
className?: string;
}
const ArrowRightIcon = (params: IconProps) => {
return (
<svg xmlns="http://www.w3.org/2000/svg" className={params.className} viewBox="0 0 24 24">
<path fill="currentColor" d="M8.59 16.586L13.177 12L8.59 7.414L10 6l6 6-6 6-1.414-1.414z" />
</svg>
);
}
interface ButtonGooeyProps {
children?: React.ReactNode;
onClick?: () => void;
disabled?: boolean;
}
const ButtonGooey = (params: ButtonGooeyProps) => {
return (
<>
<div className="wrapper">
<button className="button" onClick={params.onClick} disabled={params.disabled}>
{params.children}
<div className="bubble">
<ArrowRightIcon className="h-8 w-8" />
</div>
</button>
</div>
<svg className="absolute hidden" width="0" height="0" xmlns="http://www.w3.org/2000/svg" version="1.1">
<defs>
<filter id="gooey">
<feGaussianBlur in="SourceGraphic" stdDeviation="10" result="blur" />
<feColorMatrix in="blur" mode="matrix" values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 20 -10" result="gooey" />
<feComposite in="SourceGraphic" in2="gooey" operator="atop" />
</filter>
</defs>
</svg>
<style jsx>{`
.wrapper {
filter: url("#gooey");
height: 100%;
width: 100%;
display: flex;
justify-content: center;
align-items: center;
}
.button {
background: #fff;
color: #000;
display: inline-flex;
font-weight: bold;
padding: 0 24px 0 24px;
border-radius: 12px;
font-size: 1.25rem;
line-height: 1.25rem;
height: 64px;
align-items: center;
}
.bubble {
color: #000;
z-index: -10;
display: flex;
background: #fff;
align-items: center;
justify-content: center;
width: 64px;
height: 64px;
position: absolute;
content: "";
border-radius: 12px;
transition: transform 0.8s;
transition-timing-function: bezier(0.2, 0.8, 0.2, 1.2);
transform: translateX(80%) translateY(0%);
}
.button:hover .bubble {
transform: translateX(210%) translateY(0%);
}
`}</style>
</>
);
};
export default ButtonGooey;