File size: 3,875 Bytes
0baa396
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
"use client";

import { motion, AnimatePresence } from "framer-motion";
import { Mic, MicOff } from "lucide-react";

interface VoiceButtonProps {
  isRecording: boolean;
  onToggle: () => void;
}

export function VoiceButton({ isRecording, onToggle }: VoiceButtonProps) {
  return (
    <div className="relative">
      {/* Pulsing rings when recording */}
      <AnimatePresence>
        {isRecording && (
          <>
            <motion.div
              className="absolute inset-0 rounded-full"
              style={{ border: "2px solid #a1a1aa" }}
              initial={{ scale: 1, opacity: 0.6 }}
              animate={{ scale: 1.8, opacity: 0 }}
              transition={{ duration: 1.5, repeat: Infinity, ease: "easeOut" }}
            />
            <motion.div
              className="absolute inset-0 rounded-full"
              style={{ border: "2px solid #a1a1aa" }}
              initial={{ scale: 1, opacity: 0.4 }}
              animate={{ scale: 2.2, opacity: 0 }}
              transition={{
                duration: 1.5,
                repeat: Infinity,
                ease: "easeOut",
                delay: 0.3,
              }}
            />
            <motion.div
              className="absolute inset-0 rounded-full"
              style={{ border: "1px solid #a1a1aa" }}
              initial={{ scale: 1, opacity: 0.3 }}
              animate={{ scale: 2.6, opacity: 0 }}
              transition={{
                duration: 1.5,
                repeat: Infinity,
                ease: "easeOut",
                delay: 0.6,
              }}
            />
          </>
        )}
      </AnimatePresence>

      {/* Glow background */}
      <AnimatePresence>
        {isRecording && (
          <motion.div
            className="absolute inset-0 rounded-full"
            style={{ backgroundColor: "#a1a1aa30" }}
            initial={{ scale: 1 }}
            animate={{ scale: 1.2 }}
            exit={{ scale: 1 }}
            transition={{ duration: 0.3 }}
          />
        )}
      </AnimatePresence>

      {/* Main button */}
      <motion.button
        onClick={onToggle}
        className={`relative z-10 w-9 h-9 rounded-full flex items-center justify-center transition-colors ${
          isRecording
            ? "bg-foreground text-background shadow-[0_0_20px_#a1a1aa40]"
            : "bg-foreground/10 text-foreground hover:bg-foreground/15 border border-border"
        }`}
        whileTap={{ scale: 0.9 }}
        whileHover={{ scale: 1.05 }}
        aria-label={isRecording ? "Stop recording" : "Start voice recording"}
      >
        {isRecording ? (
          <motion.div
            animate={{ scale: [1, 1.2, 1] }}
            transition={{ duration: 0.8, repeat: Infinity }}
          >
            <MicOff className="w-3.5 h-3.5" />
          </motion.div>
        ) : (
          <Mic className="w-3.5 h-3.5" />
        )}
      </motion.button>
    </div>
  );
}

/** Simple waveform visualization component */
export function WaveformVisualizer({ isActive }: { isActive: boolean }) {
  const bars = 24;

  return (
    <div className="flex items-center justify-center gap-[2px] h-8">
      {Array.from({ length: bars }).map((_, i) => (
        <motion.div
          key={i}
          className="w-[3px] rounded-full"
          style={{ backgroundColor: isActive ? "#a1a1aa" : "#3f3f4640" }}
          animate={
            isActive
              ? {
                  height: [4, Math.random() * 28 + 4, 4],
                }
              : { height: 4 }
          }
          transition={
            isActive
              ? {
                  duration: 0.4 + Math.random() * 0.3,
                  repeat: Infinity,
                  repeatType: "reverse",
                  delay: i * 0.03,
                }
              : { duration: 0.3 }
          }
        />
      ))}
    </div>
  );
}