@@ -65,10 +65,30 @@ export function FloatWindow() {
6565 const [ isExpanded , setIsExpanded ] = useState ( savedState . isExpanded ?? false ) ;
6666 const [ expandDirection , setExpandDirection ] = useState < "left" | "right" > ( savedState . expandDirection ?? "right" ) ;
6767 const [ snapSide , setSnapSide ] = useState < "left" | "right" | null > ( savedState . snapSide ?? null ) ;
68- const [ hoveredId , setHoveredId ] = useState < string | null > ( null ) ;
6968 const isDraggingRef = useRef ( false ) ;
7069 const initializedRef = useRef ( false ) ;
7170
71+ // 修复无焦点时光标不显示手型的问题
72+ // WebKit 在非活动窗口中不会自动更新 CSS cursor,需要手动强制设置
73+ useEffect ( ( ) => {
74+ const handleMouseMove = ( e : MouseEvent ) => {
75+ const target = e . target as HTMLElement ;
76+ // 检查元素或其父元素是否有 cursor-pointer 类或是可点击的
77+ const isClickable = target . closest ( '.cursor-pointer, button, [role="button"], a' ) ;
78+ document . body . style . cursor = isClickable ? 'pointer' : 'default' ;
79+ } ;
80+
81+ const handleMouseLeave = ( ) => {
82+ document . body . style . cursor = 'default' ;
83+ } ;
84+
85+ document . addEventListener ( 'mousemove' , handleMouseMove ) ;
86+ document . addEventListener ( 'mouseleave' , handleMouseLeave ) ;
87+ return ( ) => {
88+ document . removeEventListener ( 'mousemove' , handleMouseMove ) ;
89+ document . removeEventListener ( 'mouseleave' , handleMouseLeave ) ;
90+ } ;
91+ } , [ ] ) ;
7292
7393 // 磁吸到边缘
7494 const snapToEdge = async ( ) => {
@@ -411,49 +431,40 @@ export function FloatWindow() {
411431
412432 { /* Items list */ }
413433 < div className = "space-y-2 max-h-56 overflow-y-auto" >
414- { items . map ( ( item , index ) => {
415- const isHovered = hoveredId === item . id ;
416- return (
417- < motion . div
418- key = { item . id }
419- initial = { { opacity : 0 , y : 10 } }
420- animate = { { opacity : 1 , y : 0 } }
421- transition = { { delay : index * 0.05 } }
422- onClick = { ( ) => handleItemClick ( item ) }
423- onMouseEnter = { ( ) => setHoveredId ( item . id ) }
424- onMouseLeave = { ( ) => setHoveredId ( null ) }
425- className = { `flex items-center gap-2 p-2 rounded-lg transition-colors cursor-pointer ${
426- isHovered ? "bg-white/20" : "bg-white/10"
427- } `}
434+ { items . map ( ( item , index ) => (
435+ < motion . div
436+ key = { item . id }
437+ initial = { { opacity : 0 , y : 10 } }
438+ animate = { { opacity : 1 , y : 0 } }
439+ transition = { { delay : index * 0.05 } }
440+ onClick = { ( ) => handleItemClick ( item ) }
441+ className = "group flex items-center gap-2 p-2 rounded-lg transition-colors cursor-pointer bg-white/10 hover:bg-white/20"
442+ >
443+ { /* tmux indicator */ }
444+ { item . tmux_session && (
445+ < Terminal className = "w-4 h-4 shrink-0 opacity-70" />
446+ ) }
447+ < div className = "flex-1 min-w-0" >
448+ < p className = "text-sm font-medium truncate" > { item . title } </ p >
449+ < p className = "text-xs opacity-70 truncate" >
450+ { item . tmux_session && (
451+ < span > { item . tmux_session } :{ item . tmux_window } .{ item . tmux_pane } · </ span >
452+ ) }
453+ { formatTime ( item . timestamp ) }
454+ </ p >
455+ </ div >
456+ < motion . button
457+ whileTap = { { scale : 0.9 } }
458+ onClick = { ( e ) => {
459+ e . stopPropagation ( ) ;
460+ handleDismiss ( item . id ) ;
461+ } }
462+ className = "p-1 rounded transition-opacity opacity-0 group-hover:opacity-100 group-hover:bg-white/10"
428463 >
429- { /* tmux indicator */ }
430- { item . tmux_session && (
431- < Terminal className = "w-4 h-4 shrink-0 opacity-70" />
432- ) }
433- < div className = "flex-1 min-w-0" >
434- < p className = "text-sm font-medium truncate" > { item . title } </ p >
435- < p className = "text-xs opacity-70 truncate" >
436- { item . tmux_session && (
437- < span > { item . tmux_session } :{ item . tmux_window } .{ item . tmux_pane } · </ span >
438- ) }
439- { formatTime ( item . timestamp ) }
440- </ p >
441- </ div >
442- < motion . button
443- whileTap = { { scale : 0.9 } }
444- onClick = { ( e ) => {
445- e . stopPropagation ( ) ;
446- handleDismiss ( item . id ) ;
447- } }
448- className = { `p-1 rounded transition-opacity ${
449- isHovered ? "opacity-100 bg-white/10" : "opacity-0"
450- } `}
451- >
452- < X className = "w-3.5 h-3.5" />
453- </ motion . button >
454- </ motion . div >
455- ) ;
456- } ) }
464+ < X className = "w-3.5 h-3.5" />
465+ </ motion . button >
466+ </ motion . div >
467+ ) ) }
457468 </ div >
458469
459470 { items . length === 0 && (
0 commit comments