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"use client"
import { useState, useEffect } from "react"
import { motion, AnimatePresence } from "framer-motion"
interface InteractionPromptProps {
isVisible: boolean
action: string
keyPrompt: string
description?: string
onInteract?: () => void
}
export default function InteractionPrompt({
isVisible = false,
action = "Interact",
keyPrompt = "E",
description,
onInteract,
}: InteractionPromptProps) {
const [keyPressed, setKeyPressed] = useState(false)
// Handle key press
useEffect(() => {
const handleKeyDown = (e: KeyboardEvent) => {
if (isVisible && e.key.toLowerCase() === keyPrompt.toLowerCase()) {
setKeyPressed(true)
if (onInteract) onInteract()
}
}
const handleKeyUp = (e: KeyboardEvent) => {
if (e.key.toLowerCase() === keyPrompt.toLowerCase()) {
setKeyPressed(false)
}
}
window.addEventListener("keydown", handleKeyDown)
window.addEventListener("keyup", handleKeyUp)
return () => {
window.removeEventListener("keydown", handleKeyDown)
window.removeEventListener("keyup", handleKeyUp)
}
}, [isVisible, keyPrompt, onInteract])
return (
<AnimatePresence>
{isVisible && (
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: 10 }}
className="fixed bottom-32 left-1/2 transform -translate-x-1/2 pointer-events-none"
>
<div className="flex flex-col items-center">
<div className="flex items-center mb-1">
<motion.div
animate={{
scale: keyPressed ? 0.9 : 1,
backgroundColor: keyPressed ? "rgba(0, 255, 255, 0.8)" : "rgba(0, 170, 255, 0.2)",
}}
className="w-8 h-8 flex items-center justify-center border border-cyan-400 text-cyan-400 font-mono text-sm font-bold mr-2"
>
{keyPrompt}
</motion.div>
<span className="text-white font-mono text-sm tracking-wide">{action}</span>
</div>
{description && (
<span className="text-cyan-300/80 font-mono text-xs max-w-xs text-center">{description}</span>
)}
<motion.div
animate={{
opacity: [0.3, 1, 0.3],
}}
transition={{
duration: 1.5,
repeat: Number.POSITIVE_INFINITY,
ease: "linear",
}}
className="w-24 h-px bg-gradient-to-r from-transparent via-cyan-400 to-transparent mt-2"
/>
</div>
</motion.div>
)}
</AnimatePresence>
)
}