web/app/components/canopy-logo.tsxblame
View source
9f470a71"use client";
9f470a72
9f470a73import { useCallback, useId, useRef } from "react";
9f470a74
603c6c95interface Props {
603c6c96 size?: number;
603c6c97}
603c6c98
603c6c99export function CanopyLogo({ size = 24 }: Props) {
9f470a710 const svgRef = useRef<SVGSVGElement>(null);
9f470a711 const id = useId();
9f470a712 const s = id.replace(/:/g, "");
9f470a713
9f470a714 const onMouseMove = useCallback((e: React.MouseEvent<SVGSVGElement>) => {
9f470a715 const rect = e.currentTarget.getBoundingClientRect();
9f470a716 const relX = ((e.clientX - rect.left) / rect.width - 0.5) * 2;
9f470a717 e.currentTarget.style.setProperty("--sway", `${relX * 5}deg`);
9f470a718 }, []);
9f470a719
9f470a720 const onMouseLeave = useCallback((e: React.MouseEvent<SVGSVGElement>) => {
9f470a721 e.currentTarget.style.setProperty("--sway", "0deg");
9f470a722 }, []);
9f470a723
603c6c924 return (
603c6c925 <svg
9f470a726 ref={svgRef}
9f470a727 className={`canopy-logo-${s}`}
603c6c928 width={size}
603c6c929 height={size}
603c6c930 viewBox="0 0 64 64"
603c6c931 fill="none"
9f470a732 onMouseMove={onMouseMove}
9f470a733 onMouseLeave={onMouseLeave}
603c6c934 >
9f470a735 <style>{`
9f470a736 .canopy-logo-${s} {
9f470a737 cursor: pointer;
9f470a738 transition: transform 0.5s cubic-bezier(0.25, 1, 0.5, 1);
9f470a739 }
9f470a740 .canopy-logo-${s}:hover,
9f470a741 .hover-row:hover .canopy-logo-${s} {
9f470a742 transform: translateY(-2px);
9f470a743 }
9f470a744 .canopy-logo-${s} .cl-bg {
9f470a745 transition: filter 0.6s ease;
9f470a746 }
9f470a747 .canopy-logo-${s}:hover .cl-bg,
9f470a748 .hover-row:hover .canopy-logo-${s} .cl-bg {
9f470a749 filter: brightness(0.9);
9f470a750 }
9f470a751 .canopy-logo-${s} .cl-canopy {
9f470a752 transform-origin: 31px 42px;
9f470a753 transform: rotate(var(--sway, 0deg));
9f470a754 transition: transform 0.8s cubic-bezier(0.34, 1.56, 0.64, 1);
9f470a755 }
9f470a756 .canopy-logo-${s}:hover .cl-canopy,
9f470a757 .hover-row:hover .canopy-logo-${s} .cl-canopy {
9f470a758 transition: transform 0.15s ease-out;
9f470a759 }
9f470a760 .canopy-logo-${s} .cl-trunk {
9f470a761 transition: stroke-width 0.4s cubic-bezier(0.25, 1, 0.5, 1);
9f470a762 }
9f470a763 .canopy-logo-${s}:hover .cl-trunk,
9f470a764 .hover-row:hover .canopy-logo-${s} .cl-trunk {
9f470a765 stroke-width: 3.2;
9f470a766 }
9f470a767 .canopy-logo-${s} .cl-root {
9f470a768 transition: stroke-width 0.4s cubic-bezier(0.25, 1, 0.5, 1) 0.05s;
9f470a769 }
9f470a770 .canopy-logo-${s}:hover .cl-root,
9f470a771 .hover-row:hover .canopy-logo-${s} .cl-root {
9f470a772 stroke-width: 2.2;
9f470a773 }
9f470a774 `}</style>
9f470a775
9f470a776 <circle cx="32" cy="32" r="32" fill="var(--accent)" className="cl-bg" />
9f470a777 <g className="cl-canopy">
9f470a778 <path className="cl-trunk" d="M31 42 L30 53" stroke="white" strokeWidth="2.5" strokeLinecap="round"/>
9f470a779 <path className="cl-root" d="M30.5 46 L34 49.5" stroke="white" strokeWidth="1.5" strokeLinecap="round"/>
9f470a780 <path d="
9f470a781 M31 42
9f470a782 C18 40, 11 32, 14 24
9f470a783 C16 17, 24 12, 31 14
9f470a784 C33 10, 40 12, 43 16
9f470a785 C48 14, 52 22, 49 28
9f470a786 C52 34, 46 40, 38 40
9f470a787 C36 42, 33 43, 31 42
9f470a788 Z
9f470a789 " fill="white"/>
9f470a790 </g>
603c6c991 </svg>
603c6c992 );
603c6c993}