/ src / components / ConnectWallet / ConnectWallet.tsx
ConnectWallet.tsx
  1  import * as React from 'react';
  2  import { cva, type VariantProps } from 'class-variance-authority';
  3  import { cn } from '../../lib/utils';
  4  
  5  /**
  6   * ConnectWallet button variants using ACDC design system tokens
  7   *
  8   * The default variant uses a gradient from Alpha (blue) to Delta (amber)
  9   * to represent the dual-chain nature of ACDC.
 10   */
 11  const connectWalletVariants = cva(
 12    // Base styles
 13    [
 14      'inline-flex items-center justify-center font-semibold',
 15      'transition-all duration-200 ease-out',
 16      'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2',
 17      'disabled:pointer-events-none disabled:opacity-50',
 18      'hover:opacity-90 active:scale-[0.98]',
 19    ],
 20    {
 21      variants: {
 22        size: {
 23          sm: 'h-8 px-3 text-sm rounded-[var(--radius-sm)]',
 24          md: 'h-10 px-4 text-base rounded-[var(--radius-md)]',
 25          lg: 'h-12 px-6 text-lg rounded-[var(--radius-lg)]',
 26        },
 27        variant: {
 28          // Default uses inline style for gradient
 29          default: 'text-white focus-visible:ring-[var(--alpha-500)]',
 30          alpha: [
 31            'bg-[var(--alpha-500)] text-white',
 32            'hover:bg-[var(--alpha-600)]',
 33            'focus-visible:ring-[var(--alpha-500)]',
 34          ],
 35          delta: [
 36            'bg-[var(--delta-500)] text-white',
 37            'hover:bg-[var(--delta-600)]',
 38            'focus-visible:ring-[var(--delta-500)]',
 39          ],
 40          outline: [
 41            'bg-transparent border-2 border-[var(--alpha-500)]',
 42            'text-[var(--alpha-500)]',
 43            'hover:bg-[var(--alpha-500)] hover:text-white',
 44            'focus-visible:ring-[var(--alpha-500)]',
 45          ],
 46          ghost: [
 47            'bg-transparent text-[var(--text-secondary)]',
 48            'hover:bg-[var(--bg-tertiary)] hover:text-[var(--text-primary)]',
 49            'focus-visible:ring-[var(--alpha-500)]',
 50          ],
 51        },
 52      },
 53      defaultVariants: {
 54        size: 'md',
 55        variant: 'default',
 56      },
 57    }
 58  );
 59  
 60  export interface ConnectWalletProps
 61    extends React.ButtonHTMLAttributes<HTMLButtonElement>,
 62      VariantProps<typeof connectWalletVariants> {
 63    /** Whether the wallet is currently connecting */
 64    isConnecting?: boolean;
 65    /** Custom label to show instead of default */
 66    label?: string;
 67    /** Custom connecting label */
 68    connectingLabel?: string;
 69  }
 70  
 71  /**
 72   * ConnectWallet - ACDC branded wallet connection button
 73   * Displays "α|δ" (alpha|delta) with "Connect Wallet" on hover
 74   */
 75  const ConnectWallet = React.forwardRef<HTMLButtonElement, ConnectWalletProps>(
 76    (
 77      {
 78        className,
 79        variant = 'default',
 80        size = 'md',
 81        isConnecting = false,
 82        label = 'α|δ',
 83        connectingLabel = '...',
 84        disabled,
 85        style,
 86        ...props
 87      },
 88      ref
 89    ) => {
 90      // Gradient style for default variant (CSS vars in gradients need inline style)
 91      const gradientStyle: React.CSSProperties | undefined =
 92        variant === 'default'
 93          ? {
 94              background:
 95                'linear-gradient(to right, var(--alpha-600) 0%, var(--alpha-500) 20%, var(--alpha-400) 40%, var(--delta-400) 60%, var(--delta-500) 80%, var(--delta-600) 100%)',
 96            }
 97          : undefined;
 98  
 99      return (
100        <button
101          className={cn(connectWalletVariants({ variant, size, className }))}
102          style={{ ...gradientStyle, ...style }}
103          ref={ref}
104          disabled={disabled || isConnecting}
105          title="Connect Wallet"
106          aria-label="Connect Wallet"
107          {...props}
108        >
109          {isConnecting ? (
110            <>
111              <svg
112                className="mr-2 h-4 w-4 animate-spin"
113                xmlns="http://www.w3.org/2000/svg"
114                fill="none"
115                viewBox="0 0 24 24"
116                aria-hidden="true"
117              >
118                <circle
119                  className="opacity-25"
120                  cx="12"
121                  cy="12"
122                  r="10"
123                  stroke="currentColor"
124                  strokeWidth="4"
125                />
126                <path
127                  className="opacity-75"
128                  fill="currentColor"
129                  d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
130                />
131              </svg>
132              <span>{connectingLabel}</span>
133            </>
134          ) : (
135            <span className="inline-flex items-center">
136              <span className="text-[var(--delta-500)] text-[2em]">α</span>
137              <span className="text-white text-[2em]">|</span>
138              <span className="text-[var(--alpha-500)] text-[2em]">δ</span>
139            </span>
140          )}
141        </button>
142      );
143    }
144  );
145  ConnectWallet.displayName = 'ConnectWallet';
146  
147  export { ConnectWallet, connectWalletVariants };