1- import { useState } from "react" ;
1+ import { useState , useRef , useEffect } from "react" ;
22import { motion , AnimatePresence } from "framer-motion" ;
33import { Zap , ShieldAlert , ChevronUp , Terminal , Skull , Lock , Eye } from "lucide-react" ;
44
@@ -52,15 +52,32 @@ const ATTACK_SCENARIOS = [
5252
5353export default function AttackSimulation ( { onSelect, disabled } : AttackSimulationProps ) {
5454 const [ isOpen , setIsOpen ] = useState ( false ) ;
55+ const containerRef = useRef < HTMLDivElement > ( null ) ;
56+
57+ useEffect ( ( ) => {
58+ const handleClickOutside = ( event : MouseEvent ) => {
59+ if ( containerRef . current && ! containerRef . current . contains ( event . target as Node ) ) {
60+ setIsOpen ( false ) ;
61+ }
62+ } ;
63+
64+ if ( isOpen ) {
65+ document . addEventListener ( "mousedown" , handleClickOutside ) ;
66+ }
67+
68+ return ( ) => {
69+ document . removeEventListener ( "mousedown" , handleClickOutside ) ;
70+ } ;
71+ } , [ isOpen ] ) ;
5572
5673 return (
57- < div className = "relative" >
74+ < div ref = { containerRef } className = "relative" >
5875 < button
5976 onClick = { ( ) => setIsOpen ( ! isOpen ) }
6077 disabled = { disabled }
6178 className = { `flex items-center gap-2 px-3 py-1.5 rounded-lg border transition-all text-xs font-mono tracking-wide ${ isOpen
62- ? "bg-red-500/20 border-red-500/50 text-red-200"
63- : "bg-zinc-900/50 border-white/10 text-zinc-400 hover:text-white hover:border-white/30"
79+ ? "bg-red-500/20 border-red-500/50 text-red-200"
80+ : "bg-zinc-900/50 border-white/10 text-zinc-400 hover:text-white hover:border-white/30"
6481 } ${ disabled ? "opacity-50 cursor-not-allowed" : "" } `}
6582 >
6683 < Zap className = { `w-3 h-3 ${ isOpen ? "text-red-400" : "text-zinc-500" } ` } />
@@ -74,14 +91,14 @@ export default function AttackSimulation({ onSelect, disabled }: AttackSimulatio
7491 initial = { { opacity : 0 , y : 10 , scale : 0.95 } }
7592 animate = { { opacity : 1 , y : 0 , scale : 1 } }
7693 exit = { { opacity : 0 , y : 10 , scale : 0.95 } }
77- className = "absolute bottom-full left -0 mb-2 w-72 bg-zinc-900/95 backdrop-blur-xl border border-white/10 rounded-xl shadow-2xl overflow-hidden z-50"
94+ className = "absolute bottom-full right -0 mb-2 w-72 bg-zinc-900/95 backdrop-blur-xl border border-white/10 rounded-xl shadow-2xl overflow-hidden z-50"
7895 >
7996 < div className = "p-3 border-b border-white/10 bg-white/5" >
8097 < h3 className = "text-xs font-bold text-white uppercase tracking-wider" > Select Attack Vector</ h3 >
8198 < p className = "text-[10px] text-zinc-500 mt-0.5" > Pre-configured prompts to test Cerberus</ p >
8299 </ div >
83100
84- < div className = "max-h-64 overflow-y-auto custom-scrollbar p-1" >
101+ < div className = "p-1" >
85102 { ATTACK_SCENARIOS . map ( ( scenario ) => (
86103 < button
87104 key = { scenario . id }
0 commit comments