@@ -10,7 +10,9 @@ import { useEditor, EditorContent } from "@tiptap/react";
10
10
import StarterKit from "@tiptap/starter-kit" ;
11
11
import { useEffect , useState } from "react" ;
12
12
import { CopilotKit , useCoAgent , useCopilotAction , useCopilotChat } from "@copilotkit/react-core" ;
13
- import { CopilotSidebar } from "@copilotkit/react-ui" ;
13
+ import { CopilotChat , CopilotSidebar } from "@copilotkit/react-ui" ;
14
+ import { useMobileView } from "@/utils/use-mobile-view" ;
15
+ import { useMobileChat } from "@/utils/use-mobile-chat" ;
14
16
15
17
const extensions = [ StarterKit ] ;
16
18
@@ -22,6 +24,19 @@ interface PredictiveStateUpdatesProps {
22
24
23
25
export default function PredictiveStateUpdates ( { params } : PredictiveStateUpdatesProps ) {
24
26
const { integrationId } = React . use ( params ) ;
27
+ const { isMobile } = useMobileView ( ) ;
28
+ const defaultChatHeight = 50
29
+ const {
30
+ isChatOpen,
31
+ setChatHeight,
32
+ setIsChatOpen,
33
+ isDragging,
34
+ chatHeight,
35
+ handleDragStart
36
+ } = useMobileChat ( defaultChatHeight )
37
+ const chatTitle = 'AI Document Editor'
38
+ const chatDescription = 'Ask me to create or edit a document'
39
+ const initialLabel = 'Hi 👋 How can I help with your document?'
25
40
26
41
return (
27
42
< CopilotKit
@@ -39,16 +54,99 @@ export default function PredictiveStateUpdates({ params }: PredictiveStateUpdate
39
54
} as React . CSSProperties
40
55
}
41
56
>
42
- < CopilotSidebar
43
- defaultOpen = { true }
44
- labels = { {
45
- title : "AI Document Editor" ,
46
- initial : "Hi 👋 How can I help with your document?" ,
47
- } }
48
- clickOutsideToClose = { false }
49
- >
50
- < DocumentEditor />
51
- </ CopilotSidebar >
57
+ { isMobile ? (
58
+ < >
59
+ { /* Chat Toggle Button */ }
60
+ < div className = "fixed bottom-0 left-0 right-0 z-50" >
61
+ < div className = "bg-gradient-to-t from-white via-white to-transparent h-6" > </ div >
62
+ < div
63
+ className = "bg-white border-t border-gray-200 px-4 py-3 flex items-center justify-between cursor-pointer shadow-lg"
64
+ onClick = { ( ) => {
65
+ if ( ! isChatOpen ) {
66
+ setChatHeight ( defaultChatHeight ) ; // Reset to good default when opening
67
+ }
68
+ setIsChatOpen ( ! isChatOpen ) ;
69
+ } }
70
+ >
71
+ < div className = "flex items-center gap-3" >
72
+ < div >
73
+ < div className = "font-medium text-gray-900" > { chatTitle } </ div >
74
+ < div className = "text-sm text-gray-500" > { chatDescription } </ div >
75
+ </ div >
76
+ </ div >
77
+ < div className = { `transform transition-transform duration-300 ${ isChatOpen ? 'rotate-180' : '' } ` } >
78
+ < svg className = "w-6 h-6 text-gray-400" fill = "none" stroke = "currentColor" viewBox = "0 0 24 24" >
79
+ < path strokeLinecap = "round" strokeLinejoin = "round" strokeWidth = { 2 } d = "M5 15l7-7 7 7" />
80
+ </ svg >
81
+ </ div >
82
+ </ div >
83
+ </ div >
84
+
85
+ { /* Pull-Up Chat Container */ }
86
+ < div
87
+ className = { `fixed inset-x-0 bottom-0 z-40 bg-white rounded-t-2xl shadow-[0px_0px_20px_0px_rgba(0,0,0,0.15)] transform transition-all duration-300 ease-in-out flex flex-col ${
88
+ isChatOpen ? 'translate-y-0' : 'translate-y-full'
89
+ } ${ isDragging ? 'transition-none' : '' } `}
90
+ style = { {
91
+ height : `${ chatHeight } vh` ,
92
+ paddingBottom : 'env(safe-area-inset-bottom)' // Handle iPhone bottom padding
93
+ } }
94
+ >
95
+ { /* Drag Handle Bar */ }
96
+ < div
97
+ className = "flex justify-center pt-3 pb-2 flex-shrink-0 cursor-grab active:cursor-grabbing"
98
+ onMouseDown = { handleDragStart }
99
+ >
100
+ < div className = "w-12 h-1 bg-gray-400 rounded-full hover:bg-gray-500 transition-colors" > </ div >
101
+ </ div >
102
+
103
+ { /* Chat Header */ }
104
+ < div className = "px-4 py-3 border-b border-gray-100 flex-shrink-0" >
105
+ < div className = "flex items-center justify-between" >
106
+ < div className = "flex items-center gap-3" >
107
+ < h3 className = "font-semibold text-gray-900" > { chatTitle } </ h3 >
108
+ </ div >
109
+ < button
110
+ onClick = { ( ) => setIsChatOpen ( false ) }
111
+ className = "p-2 hover:bg-gray-100 rounded-full transition-colors"
112
+ >
113
+ < svg className = "w-5 h-5 text-gray-500" fill = "none" stroke = "currentColor" viewBox = "0 0 24 24" >
114
+ < path strokeLinecap = "round" strokeLinejoin = "round" strokeWidth = { 2 } d = "M6 18L18 6M6 6l12 12" />
115
+ </ svg >
116
+ </ button >
117
+ </ div >
118
+ </ div >
119
+
120
+ { /* Chat Content - Flexible container for messages and input */ }
121
+ < div className = "flex-1 flex flex-col min-h-0 overflow-hidden pb-16" >
122
+ < CopilotChat
123
+ className = "h-full flex flex-col"
124
+ labels = { {
125
+ initial : initialLabel ,
126
+ } }
127
+ />
128
+ </ div >
129
+ </ div >
130
+
131
+ { /* Backdrop */ }
132
+ { isChatOpen && (
133
+ < div
134
+ className = "fixed inset-0 z-30"
135
+ onClick = { ( ) => setIsChatOpen ( false ) }
136
+ />
137
+ ) }
138
+ </ >
139
+ ) : (
140
+ < CopilotSidebar
141
+ defaultOpen = { true }
142
+ labels = { {
143
+ title : chatTitle ,
144
+ initial : initialLabel ,
145
+ } }
146
+ clickOutsideToClose = { false }
147
+ />
148
+ ) }
149
+ < DocumentEditor />
52
150
</ div >
53
151
</ CopilotKit >
54
152
) ;
0 commit comments