@@ -15,7 +15,11 @@ export default function ChatBot() {
1515 const [ isNewChat , setIsNewChat ] = useState ( true ) ;
1616 const [ chatListWidth , setChatListWidth ] = useState ( 160 ) ; // w-40 = 160px
1717 const [ isDragging , setIsDragging ] = useState ( false ) ;
18- const dragRef = useRef < HTMLDivElement > ( null ) ;
18+ const [ isResizingWidth , setIsResizingWidth ] = useState ( false ) ;
19+ const [ isResizingHeight , setIsResizingHeight ] = useState ( false ) ;
20+ const [ chatBoxWidth , setChatBoxWidth ] = useState ( ( ) => Math . max ( window . innerWidth * 0.5 , 480 ) ) ;
21+ const [ chatBoxHeight , setChatBoxHeight ] = useState ( 384 ) ;
22+ const chatBoxRef = useRef < HTMLDivElement > ( null ) ;
1923
2024 const { data : chatSessions , isLoading : isChatSessionsLoading } = useGetAllChatSessions ( ) ;
2125
@@ -29,13 +33,13 @@ export default function ChatBot() {
2933
3034 const onMouseMove = useCallback (
3135 ( e : MouseEvent ) => {
32- if ( ! isDragging || ! dragRef . current ) return ;
36+ if ( ! isDragging || ! chatBoxRef . current ) return ;
3337
34- const containerRect = dragRef . current . getBoundingClientRect ( ) ;
38+ const containerRect = chatBoxRef . current . getBoundingClientRect ( ) ;
3539 const newWidth = e . clientX - containerRect . left ;
3640
3741 // 최소 128px (w-32), 최대 160px (w-40)
38- const clampedWidth = Math . max ( 128 , Math . min ( 160 , newWidth ) ) ;
42+ const clampedWidth = Math . max ( 128 , Math . min ( containerRect . width / 3 , newWidth ) ) ;
3943 setChatListWidth ( clampedWidth ) ;
4044 } ,
4145 [ isDragging ]
@@ -47,6 +51,54 @@ export default function ChatBot() {
4751 document . body . style . userSelect = "" ;
4852 } , [ ] ) ;
4953
54+ // Width resize handlers
55+ const onResizeWidthMouseDown = ( e : React . MouseEvent ) => {
56+ e . preventDefault ( ) ;
57+ setIsResizingWidth ( true ) ;
58+ document . body . style . cursor = "ew-resize" ;
59+ document . body . style . userSelect = "none" ;
60+ } ;
61+ const onResizeWidthMouseMove = useCallback (
62+ ( e : MouseEvent ) => {
63+ if ( ! isResizingWidth || ! chatBoxRef . current ) return ;
64+ const box = chatBoxRef . current . getBoundingClientRect ( ) ;
65+ const newWidth = box . right - e . clientX ;
66+ const minWidth = 480 ; // 30rem
67+ const maxWidth = window . innerWidth * 0.5 ;
68+ setChatBoxWidth ( Math . max ( minWidth , Math . min ( maxWidth , newWidth ) ) ) ;
69+ } ,
70+ [ isResizingWidth ]
71+ ) ;
72+ const onResizeWidthMouseUp = useCallback ( ( ) => {
73+ setIsResizingWidth ( false ) ;
74+ document . body . style . cursor = "" ;
75+ document . body . style . userSelect = "" ;
76+ } , [ ] ) ;
77+
78+ // Height resize handlers
79+ const onResizeHeightMouseDown = ( e : React . MouseEvent ) => {
80+ e . preventDefault ( ) ;
81+ setIsResizingHeight ( true ) ;
82+ document . body . style . cursor = "ns-resize" ;
83+ document . body . style . userSelect = "none" ;
84+ } ;
85+ const onResizeHeightMouseMove = useCallback (
86+ ( e : MouseEvent ) => {
87+ if ( ! isResizingHeight || ! chatBoxRef . current ) return ;
88+ const box = chatBoxRef . current . getBoundingClientRect ( ) ;
89+ const newHeight = box . bottom - e . clientY ;
90+ const minHeight = 384 ; // 24rem
91+ const maxHeight = window . innerHeight - 40 ;
92+ setChatBoxHeight ( Math . max ( minHeight , Math . min ( maxHeight , newHeight ) ) ) ;
93+ } ,
94+ [ isResizingHeight ]
95+ ) ;
96+ const onResizeHeightMouseUp = useCallback ( ( ) => {
97+ setIsResizingHeight ( false ) ;
98+ document . body . style . cursor = "" ;
99+ document . body . style . userSelect = "" ;
100+ } , [ ] ) ;
101+
50102 // 마우스 이벤트 리스너 등록
51103 useEffect ( ( ) => {
52104 if ( isDragging ) {
@@ -58,7 +110,23 @@ export default function ChatBot() {
58110 document . removeEventListener ( "mouseup" , onMouseUp ) ;
59111 } ;
60112 }
61- } , [ isDragging , onMouseMove , onMouseUp ] ) ;
113+ if ( isResizingWidth ) {
114+ document . addEventListener ( "mousemove" , onResizeWidthMouseMove ) ;
115+ document . addEventListener ( "mouseup" , onResizeWidthMouseUp ) ;
116+ return ( ) => {
117+ document . removeEventListener ( "mousemove" , onResizeWidthMouseMove ) ;
118+ document . removeEventListener ( "mouseup" , onResizeWidthMouseUp ) ;
119+ } ;
120+ }
121+ if ( isResizingHeight ) {
122+ document . addEventListener ( "mousemove" , onResizeHeightMouseMove ) ;
123+ document . addEventListener ( "mouseup" , onResizeHeightMouseUp ) ;
124+ return ( ) => {
125+ document . removeEventListener ( "mousemove" , onResizeHeightMouseMove ) ;
126+ document . removeEventListener ( "mouseup" , onResizeHeightMouseUp ) ;
127+ } ;
128+ }
129+ } , [ isDragging , isResizingWidth , isResizingHeight ] ) ;
62130
63131 // 컴포넌트 언마운트 시 cleanup
64132 useEffect ( ( ) => {
@@ -75,12 +143,33 @@ export default function ChatBot() {
75143 </ button >
76144 { isOpen && (
77145 < div
78- ref = { dragRef }
79- className = "absolute bottom-0 right-full mr-2 flex h-96 w-[42rem] gap-0 rounded-lg border border-blue-400 bg-white p-2 text-black"
146+ ref = { chatBoxRef }
147+ className = "absolute bottom-0 right-full mr-2 flex gap-0 rounded-lg border border-blue-400 bg-white p-2 text-black"
148+ style = { {
149+ minWidth : "30rem" ,
150+ maxWidth : "50vw" ,
151+ minHeight : "24rem" ,
152+ maxHeight : "calc(100vh - 2.5rem)" ,
153+ width : chatBoxWidth ,
154+ height : chatBoxHeight ,
155+ overflow : "auto" ,
156+ } }
80157 >
158+ { /* Left edge resize handle */ }
159+ < div
160+ className = "absolute left-0 top-0 z-20 h-full w-2 cursor-ew-resize"
161+ style = { { userSelect : "none" } }
162+ onMouseDown = { onResizeWidthMouseDown }
163+ />
164+ { /* Top edge resize handle */ }
165+ < div
166+ className = "absolute left-0 top-0 z-20 h-2 w-full cursor-ns-resize"
167+ style = { { userSelect : "none" } }
168+ onMouseDown = { onResizeHeightMouseDown }
169+ />
81170 < ul
82171 className = "relative flex flex-col gap-2 overflow-y-auto"
83- style = { { width : `${ chatListWidth } px` } }
172+ style = { { width : `${ chatListWidth } px` , minWidth : "10rem" , maxWidth : "16rem" } }
84173 >
85174 { isChatSessionsLoading ? (
86175 < div className = "mx-auto flex h-full items-center justify-center" >
@@ -123,7 +212,7 @@ export default function ChatBot() {
123212 < div className = "absolute left-1/2 top-1/2 h-12 w-1 -translate-x-1/2 -translate-y-1/2 rounded-full bg-gray-400 transition-colors hover:bg-blue-500" />
124213 </ div >
125214
126- < div className = "min-w-0 flex-1" >
215+ < div className = "h-full min-w-0 flex-1" >
127216 < Chat
128217 sessionId = { currentSession }
129218 onSessionCreated = { setCurrentSession }
0 commit comments