← back to Dear Bubbe Nextjs

components/TalkButton.tsx

72 lines

'use client'

import { useState, useEffect } from 'react'

interface TalkButtonProps {
  onClick: () => void
  isActive?: boolean
  showPulse?: boolean
}

export default function TalkButton({ onClick, isActive = false, showPulse = true }: TalkButtonProps) {
  const [isHovered, setIsHovered] = useState(false)

  return (
    <button
      onClick={onClick}
      onMouseEnter={() => setIsHovered(true)}
      onMouseLeave={() => setIsHovered(false)}
      className={`fixed bottom-6 right-6 z-40 group transition-all transform hover:scale-110 active:scale-95 touch-manipulation ${
        isActive ? 'scale-110' : ''
      } md:bottom-6 md:right-6 sm:bottom-4 sm:right-4`}
      aria-label="Talk to Bubbe"
    >
      {/* Pulse Animation */}
      {showPulse && !isActive && (
        <>
          <div className="absolute inset-0 bg-amber-500 rounded-full animate-ping opacity-25"></div>
          <div className="absolute inset-0 bg-amber-500 rounded-full animate-ping animation-delay-200 opacity-25"></div>
        </>
      )}
      
      {/* Main Button */}
      <div className={`relative w-20 h-20 min-w-[64px] min-h-[64px] rounded-full shadow-2xl transition-all ${
        isActive 
          ? 'bg-gradient-to-br from-green-500 to-green-600' 
          : 'bg-gradient-to-br from-amber-500 to-orange-600'
      } flex items-center justify-center md:w-20 md:h-20 sm:w-16 sm:h-16`}>
        {/* Icon */}
        <div className="text-white">
          {isActive ? (
            // Active/Talking state
            <svg className="w-10 h-10 md:w-10 md:h-10 sm:w-8 sm:h-8" fill="none" stroke="currentColor" viewBox="0 0 24 24">
              <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} 
                d="M5.636 18.364a9 9 0 010-12.728m12.728 0a9 9 0 010 12.728m-9.9-2.829a5 5 0 010-7.07m7.072 0a5 5 0 010 7.07M13 12a1 1 0 11-2 0 1 1 0 012 0z" />
            </svg>
          ) : (
            // Inactive state - microphone
            <svg className="w-10 h-10 md:w-10 md:h-10 sm:w-8 sm:h-8" fill="none" stroke="currentColor" viewBox="0 0 24 24">
              <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} 
                d="M19 11a7 7 0 01-7 7m0 0a7 7 0 01-7-7m7 7v4m0 0H8m4 0h4m-4-8a3 3 0 01-3-3V5a3 3 0 116 0v6a3 3 0 01-3 3z" />
            </svg>
          )}
        </div>
        
        {/* Label on Hover - Hidden on mobile to avoid touch issues */}
        {isHovered && (
          <div className="absolute -top-12 left-1/2 transform -translate-x-1/2 bg-gray-800 text-white px-3 py-1 rounded-lg text-sm whitespace-nowrap hidden md:block">
            {isActive ? 'Bubbe is listening...' : 'Talk to Bubbe'}
            <div className="absolute bottom-0 left-1/2 transform -translate-x-1/2 translate-y-1/2 rotate-45 w-2 h-2 bg-gray-800"></div>
          </div>
        )}
      </div>
      
      {/* Text Label */}
      <div className={`mt-1 text-xs md:text-sm font-semibold transition-colors ${
        isActive ? 'text-green-600' : 'text-amber-600'
      }`}>
        {isActive ? 'TALKING' : 'TALK'}
      </div>
    </button>
  )
}