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 }
9f470a743 .canopy-logo-${s} .cl-bg {
9f470a744 transition: filter 0.6s ease;
9f470a745 }
9f470a746 .canopy-logo-${s}:hover .cl-bg,
9f470a747 .hover-row:hover .canopy-logo-${s} .cl-bg {
9f470a748 filter: brightness(0.9);
9f470a749 }
9f470a750 .canopy-logo-${s} .cl-canopy {
9f470a751 transform-origin: 31px 42px;
9f470a752 transform: rotate(var(--sway, 0deg));
9f470a753 transition: transform 0.8s cubic-bezier(0.34, 1.56, 0.64, 1);
9f470a754 }
9f470a755 .canopy-logo-${s}:hover .cl-canopy,
9f470a756 .hover-row:hover .canopy-logo-${s} .cl-canopy {
9f470a757 transition: transform 0.15s ease-out;
9f470a758 }
9f470a759 .canopy-logo-${s} .cl-trunk {
9f470a760 transition: stroke-width 0.4s cubic-bezier(0.25, 1, 0.5, 1);
9f470a761 }
9f470a762 .canopy-logo-${s}:hover .cl-trunk,
9f470a763 .hover-row:hover .canopy-logo-${s} .cl-trunk {
9f470a764 stroke-width: 3.2;
9f470a765 }
9f470a766 .canopy-logo-${s} .cl-root {
9f470a767 transition: stroke-width 0.4s cubic-bezier(0.25, 1, 0.5, 1) 0.05s;
9f470a768 }
9f470a769 .canopy-logo-${s}:hover .cl-root,
9f470a770 .hover-row:hover .canopy-logo-${s} .cl-root {
9f470a771 stroke-width: 2.2;
9f470a772 }
9f470a773 `}</style>
9f470a774
9f470a775 <circle cx="32" cy="32" r="32" fill="var(--accent)" className="cl-bg" />
9f470a776 <g className="cl-canopy">
9f470a777 <path className="cl-trunk" d="M31 42 L30 53" stroke="white" strokeWidth="2.5" strokeLinecap="round"/>
9f470a778 <path className="cl-root" d="M30.5 46 L34 49.5" stroke="white" strokeWidth="1.5" strokeLinecap="round"/>
9f470a779 <path d="
9f470a780 M31 42
9f470a781 C18 40, 11 32, 14 24
9f470a782 C16 17, 24 12, 31 14
9f470a783 C33 10, 40 12, 43 16
9f470a784 C48 14, 52 22, 49 28
9f470a785 C52 34, 46 40, 38 40
9f470a786 C36 42, 33 43, 31 42
9f470a787 Z
9f470a788 " fill="white"/>
9f470a789 </g>
603c6c990 </svg>
603c6c991 );
603c6c992}