loading
Just a moment.

Gooey Button

October 2024

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;