22
33import { BotIcon , ChevronDownIcon } from "lucide-react" ;
44
5- import { type FC , forwardRef } from "react" ;
5+ import { type FC , forwardRef , useState , useEffect } from "react" ;
66import { AssistantModalPrimitive } from "@assistant-ui/react" ;
7+ import { usePathname } from "next/navigation" ;
78
89import { Thread } from "@/app/components/assistant-ui/thread" ;
910import { TooltipIconButton } from "@/app/components/assistant-ui/tooltip-icon-button" ;
11+ import {
12+ Tooltip ,
13+ TooltipContent ,
14+ TooltipTrigger ,
15+ } from "@/app/components/ui/tooltip" ;
1016
1117interface AssistantModalProps {
1218 errorMessage ?: string ;
@@ -19,11 +25,61 @@ export const AssistantModal: FC<AssistantModalProps> = ({
1925 showSettingsAction = false ,
2026 onClearError,
2127} ) => {
28+ const [ showBubble , setShowBubble ] = useState ( false ) ;
29+
30+ useEffect ( ( ) => {
31+ // 检查本次访问是否已关闭过气泡
32+ const bubbleClosed = sessionStorage . getItem ( "ai-bubble-closed" ) ;
33+
34+ if ( ! bubbleClosed ) {
35+ // 页面加载后2秒显示气泡提示
36+ const showTimer = setTimeout ( ( ) => {
37+ setShowBubble ( true ) ;
38+ } , 2000 ) ;
39+
40+ // 15秒后自动关闭气泡
41+ const hideTimer = setTimeout ( ( ) => {
42+ setShowBubble ( false ) ;
43+ sessionStorage . setItem ( "ai-bubble-closed" , "true" ) ;
44+ } , 17000 ) ; // 2秒显示 + 15秒停留 = 17秒
45+
46+ return ( ) => {
47+ clearTimeout ( showTimer ) ;
48+ clearTimeout ( hideTimer ) ;
49+ } ;
50+ }
51+ } , [ ] ) ;
52+
53+ const handleCloseBubble = ( ) => {
54+ setShowBubble ( false ) ;
55+ // 记录本次访问已关闭气泡
56+ sessionStorage . setItem ( "ai-bubble-closed" , "true" ) ;
57+ } ;
58+
2259 return (
2360 < AssistantModalPrimitive . Root >
2461 < AssistantModalPrimitive . Anchor className = "aui-root aui-modal-anchor fixed right-4 bottom-4 size-14" >
62+ { /* 自定义气泡组件 */ }
63+ { showBubble && (
64+ < div
65+ className = "absolute bottom-17 right-0 z-40 animate-in fade-in-0 slide-in-from-bottom-2 duration-500"
66+ onClick = { handleCloseBubble }
67+ >
68+ < div className = "relative bg-gray-100/70 backdrop-blur-sm rounded-2xl shadow-lg border-2 border-black px-8 py-5 cursor-pointer hover:shadow-xl transition-all duration-200 hover:scale-105" >
69+ < div className = "text-base text-gray-800 font-medium whitespace-nowrap" >
70+ 有问题可以问我哦~
71+ </ div >
72+ { /* 气泡尾巴箭头 - 指向下方按钮 */ }
73+ < div className = "absolute -bottom-2 right-8" >
74+ < div className = "w-0 h-0 border-l-[8px] border-r-[8px] border-t-[8px] border-l-transparent border-r-transparent border-t-gray-100/70" > </ div >
75+ < div className = "absolute -top-[2px] -left-[2px] w-0 h-0 border-l-[10px] border-r-[10px] border-t-[10px] border-l-transparent border-r-transparent border-t-black" > </ div >
76+ </ div >
77+ </ div >
78+ </ div >
79+ ) }
80+
2581 < AssistantModalPrimitive . Trigger asChild >
26- < AssistantModalButton />
82+ < AssistantModalButton onCloseBubble = { handleCloseBubble } />
2783 </ AssistantModalPrimitive . Trigger >
2884 </ AssistantModalPrimitive . Anchor >
2985 < AssistantModalPrimitive . Content
@@ -40,21 +96,37 @@ export const AssistantModal: FC<AssistantModalProps> = ({
4096 ) ;
4197} ;
4298
43- type AssistantModalButtonProps = { "data-state" ?: "open" | "closed" } ;
99+ type AssistantModalButtonProps = {
100+ "data-state" ?: "open" | "closed" ;
101+ onCloseBubble ?: ( ) => void ;
102+ onClick ?: ( e : React . MouseEvent ) => void ;
103+ } ;
44104
45105const AssistantModalButton = forwardRef <
46106 HTMLButtonElement ,
47107 AssistantModalButtonProps
48- > ( ( { "data-state" : state , ...rest } , ref ) => {
108+ > ( ( { "data-state" : state , onCloseBubble , ...rest } , ref ) => {
49109 const tooltip = state === "open" ? "Close Assistant" : "Open Assistant" ;
50110
111+ const handleClick = ( e : React . MouseEvent ) => {
112+ // 当点击open按钮时,关闭气泡对话
113+ if ( onCloseBubble ) {
114+ onCloseBubble ( ) ;
115+ }
116+ // 继续执行原有的点击事件
117+ if ( rest . onClick ) {
118+ rest . onClick ( e ) ;
119+ }
120+ } ;
121+
51122 return (
52123 < TooltipIconButton
53124 variant = "default"
54125 tooltip = { tooltip }
55126 side = "left"
56127 { ...rest }
57- className = "aui-modal-button size-full rounded-full shadow transition-transform hover:scale-110 active:scale-90"
128+ onClick = { handleClick }
129+ className = "aui-modal-button size-full rounded-full shadow transition-transform hover:scale-110 active:scale-90 cursor-pointer"
58130 ref = { ref }
59131 >
60132 < BotIcon
0 commit comments