Button Ripple
November 2024
TSX
import React, { MouseEvent } from "react";
type ButtonRippleEffectProps = {
variant: "neutral" | "blue" | "green" | "red";
};
const spanCn = {
neutral: "bg-neutral-100 dark:bg-neutral-600",
blue: "bg-blue-100",
green: "bg-green-100",
red: "bg-red-100",
};
const buttonCn = {
neutral: "bg-[#101010] text-neutral-50 border-white/10",
blue: "bg-cyan-600 text-cyan-200 border-cyan-400/50",
green: "bg-green-600 text-green-200 border-green-400/50",
red: "bg-red-600 text-red-200 border-red-400/50",
};
export const ButtonRippleEffect: React.FC<ButtonRippleEffectProps> = ({
variant,
}) => {
const handleClick = (e: MouseEvent<HTMLButtonElement>) => {
const button = e.currentTarget;
const x = e.clientX - button.getBoundingClientRect().left;
const y = e.clientY - button.getBoundingClientRect().top;
const ripples = document.createElement("span");
ripples.style.cssText = `
left: ${x}px;
top: ${y}px;
position: absolute;
transform: translate(-50%, -50%);
pointer-events: none;
border-radius: 50%;
animation: ripple 1.4s linear infinite;
transition: 0.5s;`;
ripples.classList.add(...spanCn[variant].split(" "));
button.appendChild(ripples);
setTimeout(() => {
ripples.remove();
}, 1400);
};
return (
<>
<button
className={`relative overflow-hidden rounded-full px-6 py-1 text-sm leading-8 border-solid border transition-colors duration-300 ${buttonCn[variant]}`}
onClick={handleClick}
>
View on Git
</button>
<style jsx>{`
@keyframes ripple {
0% {
width: 0;
height: 0;
opacity: 0.5;
}
100% {
width: 520px;
height: 520px;
opacity: 0;
}
}
`}</style>
</>
);
};
export default ButtonRippleEffect;