/ src / components / Spinner / Spinner.tsx
Spinner.tsx
 1  import * as React from 'react'
 2  import { cn } from '../../lib/utils'
 3  
 4  export interface SpinnerProps {
 5    size?: 'xs' | 'sm' | 'md' | 'lg'
 6    color?: 'alpha' | 'delta' | 'testnet' | 'neutral'
 7    className?: string
 8    label?: string
 9  }
10  
11  const sizeMap = { xs: 'h-3 w-3', sm: 'h-4 w-4', md: 'h-6 w-6', lg: 'h-8 w-8' }
12  const colorMap = {
13    alpha:   'var(--alpha-500)',    // electric blue — oklch(60% 0.26 258)
14    delta:   'var(--delta-500)',    // bright amber  — oklch(80% 0.20 79)
15    testnet: 'var(--testnet-500)',  // orange        — oklch(72% 0.21 50)
16    neutral: 'currentColor',
17  }
18  
19  export function Spinner({ size = 'md', color = 'alpha', className, label = 'Loading...' }: SpinnerProps) {
20    return (
21      <svg
22        className={cn('animate-spin', sizeMap[size], className)}
23        xmlns="http://www.w3.org/2000/svg"
24        fill="none"
25        viewBox="0 0 24 24"
26        role="status"
27        aria-label={label}
28        style={{ color: colorMap[color] }}
29      >
30        <circle
31          className="opacity-25"
32          cx="12"
33          cy="12"
34          r="10"
35          stroke="currentColor"
36          strokeWidth="4"
37        />
38        <path
39          className="opacity-75"
40          fill="currentColor"
41          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"
42        />
43      </svg>
44    )
45  }