← back to IWasCute

src/components/licensor/Stepper.tsx

140 lines

'use client'

import { motion } from 'framer-motion'
import { Check } from 'lucide-react'
import clsx from 'clsx'

const STEPS = [
  { label: 'Upload Photos', shortLabel: 'Upload' },
  { label: 'Copyright Info', shortLabel: 'Copyright' },
  { label: 'Likeness Release', shortLabel: 'Release' },
  { label: 'Review & Submit', shortLabel: 'Review' },
]

interface StepperProps {
  currentStep: number
}

export default function Stepper({ currentStep }: StepperProps) {
  return (
    <div className="w-full px-4 py-6 md:px-8 md:py-8">
      <div className="max-w-2xl mx-auto">
        <div className="flex items-center justify-between relative">
          {/* Connecting lines (behind circles) */}
          <div
            className="absolute top-5 left-0 right-0 h-0.5 mx-12 md:mx-16"
            style={{ background: 'var(--color-cream-dark)' }}
          />
          {/* Animated filled progress line */}
          <div
            className="absolute top-5 left-0 h-0.5 mx-12 md:mx-16 transition-all duration-700 ease-in-out"
            style={{
              background: 'var(--color-sage)',
              right: 0,
              width: `calc(${(currentStep / (STEPS.length - 1)) * 100}% - 6rem)`,
            }}
          />

          {STEPS.map((step, index) => {
            const isCompleted = index < currentStep
            const isActive = index === currentStep
            const isUpcoming = index > currentStep

            return (
              <div
                key={step.label}
                className="relative flex flex-col items-center gap-2 z-10"
              >
                {/* Circle */}
                <motion.div
                  initial={false}
                  animate={{
                    scale: isActive ? 1.12 : 1,
                  }}
                  transition={{ type: 'spring', stiffness: 300, damping: 25 }}
                  className={clsx(
                    'w-10 h-10 rounded-full flex items-center justify-center',
                    'text-sm font-bold transition-colors duration-300',
                    'shadow-sm',
                    {
                      'text-white': isCompleted || isActive,
                    }
                  )}
                  style={{
                    background: isCompleted
                      ? 'var(--color-sage-dark)'
                      : isActive
                        ? 'var(--color-peach)'
                        : 'var(--color-cream)',
                    border: isUpcoming
                      ? '2px solid var(--color-cream-dark)'
                      : 'none',
                    color: isUpcoming
                      ? 'var(--color-warm-gray)'
                      : 'var(--color-brown)',
                  }}
                  aria-current={isActive ? 'step' : undefined}
                  aria-label={`Step ${index + 1}: ${step.label}${isCompleted ? ' (completed)' : isActive ? ' (current)' : ''}`}
                >
                  {isCompleted ? (
                    <Check size={16} strokeWidth={3} />
                  ) : (
                    <span>{index + 1}</span>
                  )}
                </motion.div>

                {/* Label */}
                <span
                  className={clsx(
                    'text-xs font-medium tracking-wide text-center',
                    'hidden sm:block',
                    {
                      'font-semibold': isActive,
                    }
                  )}
                  style={{
                    color: isActive
                      ? 'var(--color-brown)'
                      : isCompleted
                        ? 'var(--color-sage-dark)'
                        : 'var(--color-warm-gray)',
                  }}
                >
                  {step.label}
                </span>
                {/* Short label for mobile */}
                <span
                  className={clsx(
                    'text-xs font-medium tracking-wide text-center',
                    'sm:hidden',
                    {
                      'font-semibold': isActive,
                    }
                  )}
                  style={{
                    color: isActive
                      ? 'var(--color-brown)'
                      : isCompleted
                        ? 'var(--color-sage-dark)'
                        : 'var(--color-warm-gray)',
                  }}
                >
                  {step.shortLabel}
                </span>
              </div>
            )
          })}
        </div>

        {/* Step counter (mobile) */}
        <p
          className="mt-4 text-center text-xs sm:hidden"
          style={{ color: 'var(--color-warm-gray)' }}
        >
          Step {currentStep + 1} of {STEPS.length}: {STEPS[currentStep].label}
        </p>
      </div>
    </div>
  )
}